I am new to Django. I am writing the first project, I came across the following problem.
We have a 'Post' model with a 'district' field. And there is a "District" model. How to dynamically change the entry number when creating a journal entry (via the admin panel). For example, there are already 3 records with area #1, and when creating the next record, number 4 is automatically filled in. Or maybe there is a way to automatically fill in the number, immediately after creating the record?
I have already achieved the automatic creation of the record number through the function. But now it does not take into account different district, but numbers all records in order, regardless of the selected district.
class Post(models.Model):
"""Post in journal."""
def auto_number_post():
all_posts = Post.objects.all()
if all_posts:
next_number = max(all_posts, key=lambda x: x.number_post)
return next_number.number_post + 1
return 1
number_post = models.PositiveIntegerField(
default=auto_number_post,
unique=True,
)
district = models.ForeignKey(
'District',
blank=False,
null=True,
on_delete=models.SET_NULL,
related_name='posts',
)
class District(models.Model):
title = models.CharField(max_length=100)
If you want the number to be the total, disregarding district, than the field is redundant as pk
is already an auto-incrementing positive integer.
otherwise, if you want it to take district into account, creating a Custom Admin Form could automatically set the number during the save and the user won't even see the field!
The downside being you can't edit that number outside of the Shell.. but why would you edit it?
that unique=True
has to be removed, as there will be a post #1 for district A and a post #1 for district B
from django import forms
from .models import Post
class PostForm(forms.ModelForm):
class Meta:
model = Post
fields = ['district']
def __init__(self, *args, **kwargs):
# Set instance to a class attr so it can be accessed in .save()
self.instance = kwargs.get('instance')
super().__init__(*args, **kwargs)
def save(self, *args, commit=True, **kwargs):
obj = super().save(commit=False, *args, **kwargs)
# Fetch the last number like this in case none exist yet!
# + make the db do the work!
most_recent = Post.objects.filter(district=obj.district).order_by('-number_post').first()
obj.number_post = most_recent.number_post + 1 if most_recent else 1
if commit:
obj.save()
return obj
from django.contrib import admin
from .forms import PostForm
from .models import Post
class PostAdmin(admin.ModelAdmin):
form = PostForm
admin.site.register(Post, PostAdmin)
You can also use this same form in views and it'll have the same functionality! I'd advise going in this direction instead of doing the dynamic default.