Django admin site foreign key - python

I have created some classes like STATE, DISTRICT, TALUK, and VILLAGE. Admin needs to add details in the admin panel.
If the admin needs to add TALUK, he must select provided STATE, DISTRICT.I used a foreign key in the TALUK class for calling states and districts. But in admin after selecting STATE, the DISTRICT dropdown shows all the DISTRICTS. I need to get only the districts of that particular state
This is the code I wrote in models.py
class STATE(models.Model):
state_name=models.CharField(max_length=25)
def __str__(self):
return self.state_name
class DISTRICT(models.Model):
district_state=models.ForeignKey(STATE,on_delete=models.CASCADE)
district_name=models.CharField(max_length=25)
def __str__(self):
return self.district_name
class TALUK(models.Model):
taluk_state=models.ForeignKey(STATE,default=1,verbose_name="state",on_delete=models.CASCADE)
taluk_district=models.ForeignKey(DISTRICT,on_delete=models.CASCADE)
taluk_name=models.CharField(max_length=25)
def __str__(self):
return self.taluk_name
class VILLAGE(models.Model):
taluk_vill=models.ForeignKey(TALUK,on_delete=models.CASCADE)
vill_name=models.CharField(max_length=25)
def __str__(self):
return self.vill_name

Related

Django search field in the database

is it possible to change my display employe to a search block because when I select the numbers it displays a list which is not practical when I have a lot of numbers in my database.
add info to an existing employee
You can define __str__() method for your Employee model, it result would be seen in admin dropdown
class Employee(models.Model):
first_name = models.CharField(max_length=50)
...
def __str__(self):
return self.first_name

Django: Custom permissions for group-based model

I'm new to Django and StackOverflow so please be a bit chill with me! I will update the code and everything as per requests.
I'm currently working on a system where students can join groups called Societies. These Societies have a ManyToManyField relationship with Users. I have been trying to think of a way to build a system where within each Society, there are Leaders and general members. Leaders can promote members to be fellow leaders, delete posts in the society, or even kick members of the society.
I would love some guidance in the right direction on how to structure (or re-structure!) my code. Specifically, I would like to know how to incorporate a "Leader" group of users with custom permissions like the one described above, that I can then use in my templates. Thank you!
class Society(models.Model):
name = models.CharField(max_length = 200)
description = models.TextField()
members = models.ManyToManyField(User, verbose_name=("Members"))
def __str__(self):
return f"{self.name}"
class SocPost(models.Model):
title = models.CharField(max_length = 100)
content = models.TextField()
date_posted = models.DateTimeField(default=timezone.now)
author = models.ForeignKey(User, on_delete=models.CASCADE)
society = models.ForeignKey(Society, on_delete=models.CASCADE, related_name="posts")
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse('post-detail', kwargs={'society_id':self.society.id, 'pk':self.pk})
Simplest solution is to use a through model:
class SocietyMembership(models.Model)
member = models.ForeignKey(User, related_name='society_membership')
society = models.ForeignKey('Society')
is_leader = models.BooleanField(default=False)
class Society(models.Model):
name = models.CharField(max_length = 200)
description = models.TextField()
members = models.ManyToManyField(
User,
verbose_name=("Members"),
related_name='societies',
through=SocietyMembership
)
def __str__(self):
return f"{self.name}"
This avoids extra queries injected by ContentTypes and the need to create one leader group per society in order to separate permissions from one group to the next.
Update:
Model update:
class Society(models.Model):
name = models.CharField(max_length=200)
description = models.TextField()
members = models.ManyToManyField(
User,
verbose_name=_("Members"),
related_name="societies",
through=SocietyMembership,
)
#property
def leaders(self):
return self.memberships.filter(is_leader=True)
def user_is_leader(self, user: User):
return self.memberships.filter(is_leader=True, member=user).exists()
def is_member(self, user: User):
return self.members.filter(pk=user.id).exists()
def __str__(self):
return f"{self.name}"
def enroll(self, user: User, as_leader: bool = False):
# Django >= 2.2, which it should be in July 2020
self.members.add(user, through_defaults={"is_leader": as_leader})
def promote(self, user: User) -> bool:
try:
membership = self.memberships.get(member=user)
except SocietyMembership.DoesNotExist:
return False
membership.is_leader = True
membership.save()
return True
def kick(self, user: User):
self.memberships.filter(member=user).delete()
Example of a views with permission check:
from django.views import generic
from django.contrib.auth.mixins import UserPassesTestMixin, LoginRequiredMixin
from . import models
class SocietyList(LoginRequiredMixin, generic.ListView):
model = models.Society
template_name = "main/society-list.html"
context_object_name = "societies"
class SocietyDetail(UserPassesTestMixin, generic.DetailView):
model = models.Society
template_name = "main/society-detail.html"
context_object_name = "society"
def test_func(self):
# self.object will be an instance of Society
if not hasattr(self, "object"):
setattr(self, "object", self.get_object())
return self.object.is_member(self.request.user)
It seems like you want your 'leaders' to be an admin, denoted by the 'is_superuser' field in the default django user model. What you described are typical admin activities in Django (and can easily be done in the django admin panel). Create one of these superusers by executing python manage.py createsuperuser and then you will have access to the admin panel where you can customize everything you need, and promote more users to admin level. If you are looking for some level of leadership between basic user and admin, you can create users with custom permissions dependent on the user_permissions field, denoted by some sort of variable which you add to the django default user model using a 1:1 relationship.

Django admin site adding "city object" instead of "City"

I'm trying to create a basic weather forecast site on Django and this error arises. I successfully made a "Cities" section but when adding any city name, "City Object 1" is added. This then creates errors when reading JSON from the API key.
from django.db import models
class City(models.Model):
name = models.CharField(max_length=25)
def _str_(self): #show the actual city name on the dashboard
return self.name
class Meta: #show the plural of city as cities instead of citys
verbose_name_plural = 'cities'
admin.py
from django.contrib import admin
from .models import City
admin.site.register(City)
two undersccore
def __str__(self):
https://docs.djangoproject.com/en/3.0/ref/models/instances/#other-model-instance-methods

How to make a model having two foreign Key relations with the different models

I have made an app in which i have made three models as below:
from django.db import models
class Class_Mgmt(models.Model):
class_name = models.CharField(max_length=8,null=False,blank=False)
def __str__(self):
return self.class_name
class Section_Mgmt(models.Model):
stu_class=models.ForeignKey(Class_Mgmt)
section_name=models.CharField(max_length=1,null=False,blank=False)
def __str__(self):
return self.section_name
class Teacher_Mgmt(models.Model):
teacher_name=models.CharField(max_length=50,null=False,blank=False)
tea_class=models.ForeignKey(Class_Mgmt)
tea_section=models.ForeignKey(Section_Mgmt)
def __str__(self):
return self.teacher_name
Here, Section_Mgmt class has a foreignKey relation with Class_Mgmt that means when i run the project and add a new section_name, then class_name will be selected from a drop-down list of all the existing classes. It is working well in the project.
But, in the Teacher_Mgmt model, i want to do like this: When i enter a new teacher in my form, then when i select the existing class from the dropdown list, then it will only show the sections available on the selected class because, section_Mgmt model also has the foreign key relation with the class_Mgmt model.
At present, when i am running the project and enter a new teacher, and select a class from the dropdown showing all the existing classes,then is showing all the sections instead of showing only those sections available in that class.
Django does not have this functionality built in but you can use django-smart-selects. Just install this library and change the Teacher_Mgmt to the following code:
from smart_selects.db_fields import ChainedForeignKey
class Teacher_Mgmt(models.Model):
teacher_name=models.CharField(max_length=50,null=False,blank=False)
tea_class=models.ForeignKey(Class_Mgmt)
tea_section=ChainedForeignKey(
Section_Mgmt,
chained_field="tea_class",
chained_model_field="tea_class",
show_all=False,
auto_choose=True
)
def __str__(self):
return self.teacher_name

Django: creating dynamic forms

I have these models and I want to build forms based on the data:
class Location(models.Model):
name=models.CharField(max_length=255)
location_id=models.CharField(max_length=255)
organization=models.CharField(max_length=255)
def __unicode__(self):
return self.name
class Beverage(models.Model):
name=models.CharField(max_length=255)
location=models.ForeignKey(Location)
fill_to_standard=models.IntegerField(max_length=10)
order_when_below=models.IntegerField(max_length=10)
def __unicode__(self):
return self.name
class Inventory(models.Model):
location=models.ForeignKey(Location)
beverage=models.ForeignKey(Beverage)
units_reported=models.IntegerField(max_length=10)
timestamp=models.DateTimeField(auto_now=True)
Here is what I want to happen, when a user goes to update inventory for a particular location, I want them to get a form that lists out all the possible beverages for that location (the beverages differ per location) and then create an Inventory form for it that will create a new line in the Inventory table for each Beverage for that Location. Each one needs a timestamp so we can have a history. I think I get that I need formsets, but I have not had any success figuring out how to implement them for this. So, this is kind of a two-parter:
Is my model design right for this problem?
How can I make forms that depend on the number of beverages to build themselves?
Question 1: model design - I would drop the location field from the Inventory model, since it is already in the Beverage model, and is redundant. Otherwise, they look good to me.
Question 2: formsets...
forms.py
from django import forms
from my_project.my_app.models import Beverage
class InventoryForm(forms.ModelForm):
units_reported = forms.IntegerField()
class Meta:
model = Beverage
fields = ('name', 'id')
views.py
from django.forms.models import modelformset_factory
from my_project.my_app.models import Beverage, Inventory
def update_inventory(request, location_id):
InventoryFormSet = modelformset_factory(Beverage, form=InventoryForm)
qs = Beverage.objects.filter(location=location_id)
formset = InventoryFormSet(queryset=qs)
if request.method == 'POST':
formset = InventoryFormSet(request.POST)
if formset.is_valid():
for form in formset:
beverage = form.save(commit=False)
units_reported = form.cleaned_data['units_reported']
Inventory(beverage=beverage, units_reported=units_reported).save()
...
modelformset_factory will create a form for every object (Beverage) in the queryset which is filtered by the desired location, and has an extra field in the customized ModelForm to report units.

Categories

Resources