Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added plugin menu and enable multi-page printing of QR codes #16

Merged
merged 3 commits into from
Jun 25, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion MANIFEST.in
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
recursive-include netbox_qrcode/templates *.html
recursive-include netbox_qrcode/fonts *.ttf
recursive-include netbox_qrcode/fonts *.ttf
recursive-include netbox_qrcode/migrations *.py
3 changes: 1 addition & 2 deletions netbox_qrcode/__init__.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
from extras.plugins import PluginConfig
from .version import __version__


class QRCodeConfig(PluginConfig):
name = 'netbox_qrcode'
verbose_name = 'qrcode'
verbose_name = 'QR Code View'
description = 'Generate QR codes for the objects'
version = __version__
author = 'Nikolay Yuzefovich'
Expand Down
14 changes: 14 additions & 0 deletions netbox_qrcode/admin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
from django.contrib import admin
from .models import QRExtendedDevice, QRExtendedRack, QRExtendedCable

@admin.register(QRExtendedDevice)
class QRExtendedDeviceAdmin(admin.ModelAdmin):
list_display = ("device", "photo")

@admin.register(QRExtendedRack)
class QRExtendedRackAdmin(admin.ModelAdmin):
list_display = ("rack", "photo")

@admin.register(QRExtendedCable)
class QRExtendedCableAdmin(admin.ModelAdmin):
list_display = ("cable", "photo")
115 changes: 115 additions & 0 deletions netbox_qrcode/filters.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
import django_filters
from django.db import models

from dcim.models import Site, Region, Rack, Manufacturer, RackRole
from dcim.choices import DeviceStatusChoices, RackStatusChoices

from utilities.filters import TreeNodeMultipleChoiceFilter

from .models import QRExtendedDevice, QRExtendedRack, QRExtendedCable

class BaseFiltersSet(django_filters.FilterSet):

q = django_filters.CharFilter(
method='search',
label='Search',
)
region = TreeNodeMultipleChoiceFilter(
queryset=Region.objects.all(),
field_name='site__region',
lookup_expr='in',
to_field_name='slug',
label='Region (slug)',
)
site = django_filters.ModelMultipleChoiceFilter(
field_name='site__slug',
queryset=Site.objects.all(),
to_field_name='slug',
label='Site name (slug)',
)

# Recieves QuerySet in Views.py and filters based on form values, returns the resulting filtered queryset back to views.py
class SearchDeviceFilterSet(BaseFiltersSet):

status = django_filters.MultipleChoiceFilter(
choices=DeviceStatusChoices,
null_value=None
)
device_id = django_filters.ModelMultipleChoiceFilter(
queryset= QRExtendedDevice.objects.all(),
to_field_name='id',
field_name='id',
label='Device (ID)',
)
rack_id = django_filters.ModelMultipleChoiceFilter(
field_name='rack',
queryset=Rack.objects.all(),
label='Rack (ID)',
)
manufacturer = django_filters.ModelMultipleChoiceFilter(
field_name='device_type__manufacturer__slug',
queryset=Manufacturer.objects.all(),
to_field_name='slug',
label='Manufacturer (slug)',
)

class Meta:
model = QRExtendedDevice
fields = ['id', ]

def search(self, queryset, name, value):
if not value.strip():
return queryset
return queryset.filter(
models.Q(name__icontains=value)
)

class SearchRackFilterSet(BaseFiltersSet):

status = django_filters.MultipleChoiceFilter(
choices=RackStatusChoices,
null_value=None
)
role = django_filters.ModelMultipleChoiceFilter(
field_name='role__slug',
queryset=RackRole.objects.all(),
to_field_name='slug',
label='Role (slug)',
)

class Meta:
model = QRExtendedRack
fields = ['id', ]

def search(self, queryset, name, value):
if not value.strip():
return queryset
return queryset.filter(
models.Q(name__icontains=value)
)

class SearchCableFilterSet(django_filters.FilterSet):
q = django_filters.CharFilter(
method='search',
label='Search',
)

class Meta:
model = QRExtendedCable
fields = ['id', ]

def search(self, queryset, name, value):
if not value.strip():
return queryset
return queryset.filter(label__icontains=value)

def filter_device(self, queryset, name, value):
queryset = queryset.filter(
models.Q(**{'_termination_a_{}__in'.format(name): value}) |
models.Q(**{'_termination_b_{}__in'.format(name): value})
)
return queryset




78 changes: 78 additions & 0 deletions netbox_qrcode/forms.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
from django import forms
from dcim.models import Device, Site, Region, Rack, RackRole, Manufacturer
from dcim.choices import DeviceStatusChoices, RackStatusChoices

from utilities.forms import DynamicModelMultipleChoiceField, StaticSelect2Multiple, DynamicModelChoiceField


class BaseFilterForm(forms.Form):
q = forms.CharField(
required=False,
label='Search'
)
region = DynamicModelMultipleChoiceField(
queryset=Region.objects.all(),
to_field_name='slug',
required=False,
initial_params={
'sites': '$site'
}
)
site = DynamicModelMultipleChoiceField(
queryset=Site.objects.all(),
to_field_name='slug',
required=False,
query_params={
'region': '$region'
}
)


class SearchFilterFormDevice(BaseFilterForm):

status = forms.MultipleChoiceField(
choices=DeviceStatusChoices,
required=False,
widget=StaticSelect2Multiple()
)
device_id = DynamicModelMultipleChoiceField(
queryset=Device.objects.all(),
to_field_name='id',
required=False,
label='Device',
null_option='None',
)
rack_id = DynamicModelMultipleChoiceField(
queryset=Rack.objects.all(),
required=False,
label='Rack',
null_option='None',
)
manufacturer = DynamicModelMultipleChoiceField(
queryset=Manufacturer.objects.all(),
to_field_name='slug',
required=False,
label='Manufacturer'
)


class SearchFilterFormRack(BaseFilterForm):

status = forms.MultipleChoiceField(
choices=RackStatusChoices,
required=False,
widget=StaticSelect2Multiple()
)
role = DynamicModelChoiceField(
queryset=RackRole.objects.all(),
to_field_name='slug',
required=False,
null_option='None',
)


class SearchFilterFormCable(forms.Form):
q = forms.CharField(
required=False,
label='Search'
)
62 changes: 62 additions & 0 deletions netbox_qrcode/migrations/0001_initial.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
# Generated by Django 3.2 on 2021-06-22 19:53

from django.db import migrations, models
import django.db.models.deletion


class Migration(migrations.Migration):

initial = True

dependencies = [
('dcim', '0130_sitegroup'),
]

operations = [
migrations.CreateModel(
name='QRExtendedRack',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False)),
('photo', models.ImageField(upload_to='image-attachments/')),
('url', models.URLField(default='')),
('name', models.CharField(blank=True, max_length=100, null=True)),
('status', models.CharField(default='active', max_length=50)),
('rack', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='dcim.rack')),
('role', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='+', to='dcim.rackrole')),
('site', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='+', to='dcim.site')),
],
options={
'abstract': False,
},
),
migrations.CreateModel(
name='QRExtendedDevice',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False)),
('photo', models.ImageField(upload_to='image-attachments/')),
('url', models.URLField(default='')),
('name', models.CharField(blank=True, max_length=64, null=True)),
('status', models.CharField(default='active', max_length=50)),
('device', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='dcim.device')),
('device_role', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='+', to='dcim.devicerole')),
('device_type', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='+', to='dcim.devicetype')),
('rack', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='+', to='dcim.rack')),
('site', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='+', to='dcim.site')),
],
options={
'abstract': False,
},
),
migrations.CreateModel(
name='QRExtendedCable',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False)),
('photo', models.ImageField(upload_to='image-attachments/')),
('url', models.URLField(default='')),
('cable', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='dcim.cable')),
],
options={
'abstract': False,
},
),
]
Empty file.
Loading