Related
I new her and need help
I create a few models:
Customer
Orders
How to make the ADD button dynamic
If I use a filter and my url is http://127.0.0.1:8000/admin/catalog/order/?order_customer__id=3, in this case pass the following value to the button <a href="{% url opts|admin_urlname:'add ' %}?order_customer={{cl.result_list.0.order_customer.id}}"
To prompt you to fill out the form when creating a new record. Accordingly, the url should look like this
http://127.0.0.1:8000/admin/catalog/order/add/?order_customer=3
If the filter is missing url http://127.0.0.1:8000/admin/catalog/order/, the button has a default value
Accordingly, when switching to the creation form, the url has a standard value
http://127.0.0.1:8000/admin/catalog/order/add
Django 3.2.6
addons smart_selects
models.py
class Customer(models.Model):
"""docstring for Customer."""
customer_name = models.CharField(max_length=200, verbose_name='Назва юридичної особи/ФОП', help_text='Введіть поністю назву юридичної особи чи фізичної особи підприємця')
customer_inn = models.CharField(max_length=15, verbose_name='ЄДРПОУ', help_text='Введеіть ЄДРПОУ для юридичної особи чи ідентифікаційний код для ФОП')
customer_adress = models.TextField(max_length=200, verbose_name='Юридична адреса клієнта' , help_text='Притриймуйтесь формату аналогічно витягу ЄДР. Наприклад: 79000, Область, Район, Місто/Селище, вулиця/проспект Назва вулиці, Номебр будинку, квартира')
customer_ceo = models.CharField(max_length=50, verbose_name='Керівник/підписант')
class Meta:
verbose_name = 'Клієнт'
verbose_name_plural = 'Клієнти'
def __str__(self):
"""
String for representing the Model object.
"""
return self.customer_name
class Order(models.Model):
order_customer = models.ForeignKey('Customer', on_delete=models.CASCADE, verbose_name="Клієнт")
order_date = models.DateField(verbose_name='Дата заявки')
order_adress = ChainedForeignKey(
'MarketAdress',
chained_field = "order_customer",
chained_model_field= "customermarkeradress",
show_all = False,
auto_choose = True,
sort = True,
verbose_name= 'Адреса точки')
order_number = models.CharField(max_length=10, verbose_name='Номер заявки')
# oder_brand = models.ForeignKey('CustomerBrand', on_delete=models.CASCADE, verbose_name="Назва вивіски")
oder_brand = ChainedForeignKey(
'CustomerBrand',
chained_field = "order_customer",
chained_model_field= "customer",
show_all = False,
auto_choose = True,
sort = True,
verbose_name= 'Вивіска')
class Meta:
verbose_name = 'Заявка'
verbose_name_plural = 'Заявки'
def __str__(self):
"""
String for representing the Model object.
"""
return str(self.oder_brand)
admin.py
#admin.register(Customer)
class CustomerAdmin(admin.ModelAdmin):
list_display = ['customer_name', 'customer_inn', 'сontract', 'orders_lists', 'orders_add']
inlines = [OrderInline, EnvironmentActInstanceInline]
def сontract(self, obj):
link_buttom = reverse('downloadWordcontarct', args=[obj.pk])
return mark_safe(f'<a class="button" label="Догорів" href="{link_buttom}">Сформувати</a>')
сontract.short_description = "Договір"
def orders_lists(self, obj):
argsus=obj.pk
link_buttom = reverse("admin:catalog_order_changelist") + "?" + "order_customer__id=" + str(argsus)
#return format_html('{} order', link_buttom)
return mark_safe(f'<a class="button" label="Заявки" href="{link_buttom}">Перейти до заявки</a>')
orders_lists.short_description = "Заявки"
def orders_add(self, obj):
argss=obj.pk
link_buttom = reverse ("admin:catalog_order_add") + "?" + "order_customer=" + str(argss)
return mark_safe(f'<a class="button" label="Заявки" href="{link_buttom}">Створити</a>')
orders_add.short_description = "Додати заявку"
#admin.register(Order)
class OrderAdmin(admin.ModelAdmin):
list_display = ['order_customer', 'order_date', 'order_number', 'order_adress', 'oder_brand', 'butt_ord']
def butt_ord(self, obj):
link_buttom = reverse('downloadWordorder', args=[obj.pk])
return mark_safe(f'<a class="button" label="Заявка" href="{link_buttom}">Заявку</a>')
butt_ord.short_description = "Сформувати"
enter image description here
enter image description here
I use ModelChoiceField with initial value just for display (readonly field).
But value displayed is model id and I want to display customized value that will be a concatenation of 3 fields. I've override ____str____ method but it is not applyed.
I try to make customize ModelChoiceFiedl to define label_from_instance that seems to be the way to do what I want but it is not applyed...
models.py
class Utilisateur(SafeDeleteModel):
_safedelete_policy = SOFT_DELETE_CASCADE
uti_ide = models.AutoField(primary_key = True)
# pro_ide = models.ForeignKey(Projet, on_delete = models.CASCADE) # related project
projets = models.ManyToManyField(Projet, through='UtilisateurProjet')
uti_nom = models.CharField("Nom", max_length=20)
uti_pre = models.CharField("Prénom", max_length=20)
uti_mai = models.CharField("Email", max_length=40)
uti_sit = models.CharField("Equipe", max_length=20, null=True, blank=True)
uti_pro = models.CharField("Fonction/profil", max_length=200, null=True, blank=True)
uti_log = models.CharField("Log utilisateur", max_length=20, null=True, blank=True)
uti_dat = models.DateTimeField("Date log",auto_now_add=True, null=True, blank=True)
log = HistoricalRecords()
#classmethod
def options_list(cls,pro_ide):
# projet = Projet.objects.get(pro_ide=pro_ide)
# utilisateurs = Utilisateur.objects.filter(pro_ide=projet.pro_ide)
utilisateurs = Utilisateur.objects.filter(projets__pro_ide=pro_ide)
the_opts_list = [(utilisateur.uti_ide, utilisateur.uti_nom+', '+utilisateur.uti_pre) for utilisateur in utilisateurs]
the_opts_list.insert(0, (None, ''))
return the_opts_list
class Meta:
db_table = 'tbl_uti'
verbose_name_plural = 'Utilisateurs'
ordering = ['uti_ide']
def __str__(self):
return f"{self.uti_nom}, {self.uti_pre} ({self.uti_mai})"
forms.py
class UtilisateurModelChoiceField(ModelChoiceField):
def label_from_instance(self, obj):
print('label')
return obj.uti_nom+', '+obj.uti_pre+' ('+obj.uti_mai+')'
class UtilisateurProjetUpdateForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
self.request = kwargs.pop("request")
super(UtilisateurProjetUpdateForm, self).__init__(*args, **kwargs)
# print('kwargs',self.request)
# print('projet',self.request['projet'])
# print('utilisateur',self.request['utilisateur'])
PROJETS = Projet.objects.all()
UTILISATEURS = Utilisateur.objects.all()
self.fields["pro_ide"] = forms.ModelChoiceField(queryset = PROJETS, label = "Nom projet", widget = forms.HiddenInput(), initial = Projet.objects.get(pro_ide=self.request['projet']))
self.fields["uti_ide"] = UtilisateurModelChoiceField(queryset = UTILISATEURS, label = "Nom, prénom de l'utilisateur", widget = forms.TextInput(attrs={'readonly':'readonly'}), initial = Utilisateur.objects.get(uti_ide=self.request['utilisateur']),) #,to_field_name="uti_nom"
class Meta:
model = UtilisateurProjet
fields = ('pro_ide','uti_ide',)
in forms.py under that last class Meta: you need to add:
field_classes = {
'pro_ide': UtilisateurModelChoiceField,
'uti_ide': UtilisateurModelChoiceField,
}
How can I pass the foreign key values from my model to my serialised json object?
Now I have this three models,
class Fleet(models.Model):
fleet_id = models.IntegerField('Id flota', primary_key=True, unique=True)
fleet_name = models.CharField('Nombre flota', max_length=20, unique=True)
def __str__(self):
return self.fleet_name + ' ' + str(self.fleet_id)
class Device(models.Model):
dev_eui = models.CharField(max_length=16, primary_key=True, unique=True)
producer = models.CharField(max_length=20)
model = models.CharField(max_length=20)
dev_name = models.CharField(max_length=20, unique=True)
fleet_id = models.ForeignKey(Fleet, on_delete=models.CASCADE)
def __str__(self):
return self.dev_eui
class DevData(models.Model):
data_uuid = models.UUIDField(primary_key=True, default=uuid.uuid1, editable=False)
frequency = models.IntegerField()
data_1 = models.FloatField()
data_2 = models.FloatField(null=True, blank=True)
dev_eui = models.ForeignKey(Device, on_delete=models.CASCADE) #hay que saber porque añade _id
def __str__(self):
return self.dev_eui
And what I'm doing is call my view function in my JS code to obtain some data like this.
def getData(request):
ctx = {}
if request.method == 'POST':
select = int(request.POST['Select'])
data = DevData.objects.order_by('dev_eui','-data_timestamp').distinct('dev_eui')
nodes = Device.objects.all()
fleets = Fleet.objects.all()
data = loads(serializers.serialize('json', data))
nodes = loads(serializers.serialize('json', nodes))
fleets = loads(serializers.serialize('json', fleets))
ctx = {'Data':data, 'Nodes':nodes, 'Fleets':fleets}
return JsonResponse(ctx)
And inside my js file I filter it with some if else conditionals.
This works well, but I'm sure I can do it directly in my view but I don't know how. How can I obtain just one JSON object with the three models information combined?
Thank you very much!!
You can write a custom serializer like this:
from django.core.serializers.json import Serializer
class CustomSerializer(Serializer):
def end_object(self, obj):
for field in self.selected_fields:
if field == 'pk':
continue
elif field in self._current.keys():
continue
else:
try:
if '__' in field:
fields = field.split('__')
value = obj
for f in fields:
value = getattr(value, f)
if value != obj and isinstance(value, JSON_ALLOWED_OBJECTS) or value == None:
self._current[field] = value
except AttributeError:
pass
super(CustomSerializer, self).end_object(obj)
Then use it like this
serializers = CustomSerializer()
queryset = DevData.objects.all()
data = serializers.serialize(queryset, fields=('data_uuid', 'dev_eui__dev_eui', 'dev_eui__fleet_id__fleet_name'))
I have wrote an article regarding serializing nested data here. You can check that out as well.
I'm trying to save the student data from an excel file. I'm reading the excel file row-wise and mapping the data to the model fields. Now the problem is that there is a foreign key and a many-to-many field which I don't know how to save. Though I figured out the foreign key part but not able to solve the second part.
Here are the files.
views.py
def fileUpload(request):
if request.method=="POST":
form= UserDataUploadView(request.POST, request.FILES)
try:
excel_file= request.FILES["excel_file"]
except MultiValueDictKeyError: # In case the user uploads nothing
return redirect('failure_page')
# Checking the extension of the file
if str(excel_file).endswith('.xls'):
data= xls_get(excel_file, column_limit=10)
elif str(excel_file).endswith('.xlsx'):
data= xlsx_get(excel_file, column_limit=10)
else:
return redirect('failure_page')
studentData= data["Sheet1"]
print("Real Data", studentData)
# reading the sheet row-wise
a_list= studentData
list_iterator= iter(a_list)
next(list_iterator)
for detail in list_iterator:
# To find out empty cells
for data in detail:
if data==" ":
print('A field is empty')
return redirect('user_upload')
print("DATA: ", detail)
user=User.objects.create(
firstName = detail[6],
lastName = detail[7],
password = detail[8],
username = detail[9],
)
# instance=user.save(commit=false)
# Student.batch.add(detail[0])
student=Student.objects.create(
user = user,
email = detail[1],
rs_id = detail[2],
dob = detail[3],
address = detail[4],
age = detail[5],
)
student.save()
return render(request, 'classroom/admin/success_page.html', {'excel_data':studentData})
# iterating over the rows and
# getting value from each cell in row
# for row in worksheet.iter_rows():
# row_data= list()
# for cell in row:
# row_data.append(str(cell.value))
# excel_data.append(row_data)
# return render(request, 'classroom/admin/excel.html', {'excel_data':excel_data})
else:
form=UserDataUploadView()
return render(request, 'classroom/admin/fill_users.html', {
'form':form,
# 'excel_data':excel_data,
})
models.py
class Subject(models.Model):
school = models.CharField(max_length=50, null=True)
name = models.CharField(max_length=30)
color = models.CharField(max_length=7, default='#007bff')
def __str__(self):
return self.name
def get_html_badge(self):
name = escape(self.name)
color = escape(self.color)
html = '<span class="badge badge-primary" style="background-color: %s">%s</span>' % (color, name)
return mark_safe(html)
class Batch(models.Model):
name = models.CharField(max_length=30, unique=True)
school = models.CharField(max_length=50)
amount_of_fees = models.IntegerField(null=True)
subjects = models.ManyToManyField(Subject)
#property
def students(self):
return self.student_set.all()
def __str__(self):
return self.name
class Student(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, primary_key=True, default=None)
batch = models.ManyToManyField(Batch)
email = models.EmailField(null=True)
phone_number = models.CharField(max_length=10, null=True)
dob = models.DateField(blank=True, null=True, help_text="Enter in the following format : YYYY-MM-DD")
address = models.TextField(max_length=150, null=True)
age = models.IntegerField(blank=True)
image = models.ImageField(upload_to='profile_pictures', default='student_image.png', blank=True)
rs_id = models.IntegerField(blank=True,default=0)
I don't know how to put the data for batch in the excel sheet. Kindly give insight for that too.
Assuming detail[0] is the name field for the Batch model, you would do:
student_batch = Batch.objects.get(name=detail[0])
student=Student.objects.create(
user = user,
email = detail[1],
rs_id = detail[2],
dob = detail[3],
address = detail[4],
age = detail[5],
)
student.batch.add(student_batch)
student.save()
You will also need to update your Batch field on the Student model to:
batch = models.ManyToManyField(Batch, blank=True)
I'm building a site using Django for equipment management. I am currently using this tutorial to help me get started.
I would like for the url displaying in the url bar in a browser to show something such as:
127.0.0.1:8000/catalog/model/model_number
But at the moment it just shows a single integer like 1, 2, 3, etc. when I click on each individual model.
Here is my urls.py:
from django.urls import path
from . import views
urlpatterns = [
path('', views.index, name='index'),
path('books/', views.BookListView.as_view(), name='books'),
path('book/<int:pk>', views.BookDetailView.as_view(), name='book-detail'),
path('models/', views.ModelListView.as_view(), name='models'),
path('model/<int:pk>', views.ModelDetailView.as_view(), name='model-detail'),
]
I know that path('model/<int:pk>'... is the part that should be changed. I've tried path('model/model.model_number>'... but this outputs the below error:
Reverse for 'model-detail' with arguments '('2',)' not found. 1 pattern(s) tried: ['catalog\\/model\\/\\<model\\.model_number\\>$']
Here is my models.py:
from django.db import models
from django.urls import reverse #Used to generate URLs by reversing the URL patterns
import uuid
import datetime
# Create your models here.
class Genre(models.Model):
"""Model representing book genre"""
name = models.CharField(max_length = 200, help_text = 'Enter book genre')
def __str__(self):
"""String for represnting model object."""
return self.name
class Book(models.Model):
"""Model representing a book (but not a specific copy of a book)"""
title = models.CharField(max_length = 200)
author = models.ForeignKey('Author', on_delete = models.SET_NULL, null = True)
# Foreign Key used because book can only have one author, but authors can have multiple books
# Author as a string rather than object because it hasn't been declared yet in the file.
summary = models.TextField(max_length = 1000, help_text = 'Enter brief descp. of book') #TextField for longer descp.
isbn = models.CharField('ISBN', max_length = 13, help_text = '13 character ISBN number')
#ManyToManyField used because genre can contain many books. Books can cover many genres.
#Genre class has already been defined so we can specify the object above.
genre = models.ManyToManyField(Genre, help_text = 'Select genre for this book') #Genre capitalized, calling model up
def __str__(self):
"""String for representing the Model object."""
return self.title
def get_absolute_url(self):
"""returns the URL to access a detail record for this book."""
return reverse('book-detail', args=[str(self.id)])
class BookInstance(models.Model):
"""Model representing a specific copy of a book"""
id = models.UUIDField(primary_key = True, default = uuid.uuid4, help_text = 'Unique ID for this book across whole library')
book = models.ForeignKey('Book', on_delete=models.SET_NULL, null = True)
imprint = models.CharField(max_length = 200)
due_back = models.DateField(null = True, blank = True) #could do date scanned (date.now())
LOAN_STATUS = ( #could be ownership! Or make more of these for location
('m', 'Maintenance'), #being worked on, cleaned after field
('o', 'On loan'), #in the field
('a', 'Available'), #ready to go
('r', 'Reserved'), #in the field, could add one for 'being tested'
)
status = models.CharField(
max_length = 1,
choices = LOAN_STATUS,
blank = True,
default = 'm',
help_text = 'Book availability',
)
class Meta:
ordering = ['due_back']
def __str__(self):
"""String for representing the Model object."""
return f'{self.id} ({self.book.title})' #Will pop up on admin page as this
class Author(models.Model):
"""Model representing an author"""
first_name = models.CharField(max_length = 100)
last_name = models.CharField(max_length = 100)
date_of_birth = models.DateField(null = True, blank = True)
date_of_death = models.DateField('Died', null = True, blank = True)
class Meta:
ordering = ['last_name', 'first_name']
def get_absolute_url(self):
"""Returns the url to access a particular author instance."""
return reverse('author-detail', args=[str(self.id)])
def __str__(self):
"""String for representing the Model object."""
return f'{self.last_name}, {self.first_name}' #Will pop up on admin page as this
class Location(models.Model):
town_city_base = models.CharField('Town/City/Base', max_length = 25, help_text="If location is classified enter CLASSIFIED in CAPS")
state = models.CharField(max_length = 25)
country = models.CharField(max_length = 25)
class Meta:
ordering = ['town_city_base', 'state', 'country']
def get_absolute_url(self):
#Returns the url to access a particular location instance
return reverse('location-detail', args=[str(self.id)])
def __str__(self):
#String for representing the Model object
return f'{self.town_city_base}, {self.state}, {self.country}'
class Category(models.Model):
category = models.CharField('Equipment Type', max_length = 50, help_text = "Enter general category of equipment")
class Meta:
verbose_name_plural = "categories" #default would have shown as "Categorys" on admin page
def __str__(self):
return self.category
class Manufacturer(models.Model):
manufacturer = models.CharField(max_length = 50, help_text = "Original manufacturer or supplier")
def __str__(self):
return self.manufacturer
class Model(models.Model):
model_number = models.CharField('Model Number', max_length = 50)
manufacturer = models.ForeignKey('Manufacturer', on_delete = models.SET_NULL, null = True)
category = models.ForeignKey('Category', on_delete = models.SET_NULL, null = True)
description = models.TextField(max_length = 1000, help_text = "Enter brief description of product", null = True) #TextField for longer descriptions
def __str__(self):
return f'{self.model_number}..........{self.description}'
def get_absolute_url(self):
#Returns the url to access a particular location instance
return reverse('model-detail', args=[str(self.id)])
class Ownership(models.Model):
ownership = models.CharField('Ownership', max_length = 50)
class Meta:
verbose_name_plural = "Owners"
def __str__(self):
return self.ownership
def get_absolute_url(self):
return reverse('ownership-detail', args=[str(self.id)])
class ModelInstance(models.Model):
asset = models.CharField('Asset Number', max_length = 50, help_text = "Enter Weston or Government I.D. Tag Number")
model = models.ForeignKey('Model', on_delete = models.SET_NULL, null = True, help_text = "Leave blank if no model number exists")
serial = models.CharField('Serial Number', max_length = 50, null = True, blank = True, help_text = "Leave blank if no serial number exists")
location = models.ForeignKey('Location', on_delete = models.SET_NULL, null = True, help_text = "Enter current location or location after manufacturing")
ownership = models.ForeignKey('Ownership', on_delete = models.SET_NULL, null = True, help_text = "Enter current owner of equipment")
STATUS = (
('M', 'Maintenance'), #being worked on, not available
('D', 'Deployed'), #in the field
('A', 'Available'), #ready to go
('R', 'Reserved'), #Being used for classified/other project
('K', 'Broken'), #Broken
)
status = models.CharField(
max_length = 1,
choices = STATUS,
blank = True,
default = 'A',
help_text = 'Equipment Availability',
)
note = models.TextField('Notes', max_length = 1000, null = True, blank = True)
date_added = models.DateField("Date Added", default=datetime.date.today)
def __str__(self):
return f'Asset Number: {self.asset}..........Serial Number: {self.serial}..........Location: {self.location}..........Ownership: {self.ownership}'
You don't use the url to access the model's fields so
model.model_number>
is not going to help you.
If you want this url:
/catalog/model/model_number
You have to code it literally as it is:
path('catalog/model/model_number/<int:pk>/', views.ModelDetailView.as_view(), name='model-detail'),
]
It is good practice to add a backlash to the end.
Bear in mind that if the app name is catalog it is not necessary to add it to the path.
Now the pk of course is necessary to be passed to the view to retrieve the object you want, so you'll have this url in the browser:
127.0.0.1:8000/catalog/model/model_number/1/