Django Traverse Foreign Keys - python

I have 3 models and I am trying to create a dashboard with a list of Trials that spans all Client Sessions for a specific client chosen via a filter.
Here are the models:
class Trial(models.Model):
behavior_name = models.ForeignKey(Behavior, on_delete=models.CASCADE)
client_session = models.ForeignKey(Client_Session, on_delete=models.CASCADE)
frequency_input = models.PositiveIntegerField(default=0, blank=True)
duration_input = models.DurationField(blank=True, default=timedelta(minutes=0))
class Meta:
verbose_name_plural = 'trials'
def __str__(self):
return str(self.id)
class Client_Session(models.Model):
name = models.CharField(max_length=200, null=False)
session_date = models.DateField(blank=False,null=False)
client = models.ForeignKey(Client, on_delete=models.CASCADE)
behaviors = models.ManyToManyField(Behavior, null=False)
therapist = models.ForeignKey(get_user_model(), on_delete=models.CASCADE)
class Meta:
verbose_name_plural = 'clientsessions'
def __str__(self):
return self.name
class Client(models.Model):
#user = models.ForeignKey(User, on_delete=models.CASCADE)
first_name = models.CharField(max_length=200)
last_name = models.CharField(max_length=200)
date_of_birth = models.DateField(blank=True, null=True)
gender = models.CharField(max_length=10, choices=GENDER_CHOICES,blank=True)
gaurdian_first_name = models.CharField(max_length=200, blank=True)
gaurdian_last_name = models.CharField(max_length=200, blank=True)
diagnosis = models.CharField(max_length=200, choices=DIAGNOSIS_CHOICES, blank=True)
therapist = models.ForeignKey(get_user_model(), on_delete=models.CASCADE)
def __str__(self):
return self.last_name
Here is the view that im trying to create
def dashboard(request):
# filter list of client sessions by selected client
client_sessions = Client_Session.objects.filter(therapist=request.user)
client = DashboardClientFilter(request.GET, queryset=client_sessions)
client_sessions = client.qs
#Create list of Trials across Client Sessions for the filtered client
trial_list = Trial.objects.filter(client_session__client=client)

You have an error filter query you used Filter data. Expected is queryset.
Change,
trial_list = Trial.objects.filter(client_session__client=client)
into
client_sessions = client.qs
client_pks = client.qs.values_list('client_id',flat=True)
trial_list = Trial.objects.filter(client_session__client_id__in= list(client_pks))
trial_list = Trial.objects.filter(client_session__client__in= list(client_pks)).distinct() distinct() method is used to remove duplicated but it not work some databases

Related

Django Relational managers

I was trying to delete my Apllication model:
class Application(models.Model):
app_type = models.ForeignKey(ApplicationCategory, on_delete=models.CASCADE, related_name='applications')
fio = models.CharField(max_length=40)
phone_number = models.CharField(max_length=90)
organisation_name = models.CharField(max_length=100, null=True, blank=True)
aid_amount = models.PositiveIntegerField()
pay_type = models.CharField(max_length=1, choices=PAY_CHOICES, default=PAY_CHOICES[0][0])
status = models.ForeignKey(AppStatus, on_delete=models.CASCADE, related_name='applications', null=True, blank=True)
created = models.DateTimeField(auto_now_add=True)
benefactor = models.ForeignKey(Benefactor, on_delete=models.CASCADE, related_name='applications', null=True)
def __str__(self):
return f"id={self.id} li {self.fio} ning mablag\'i!"
and this was my Benefactor model:
class Benefactor(models.Model):
fio = models.CharField(max_length=255)
phone_number = models.CharField(max_length=9)
image = models.ImageField(upload_to='media/')
sponsory_money = models.IntegerField()
organisation_name = models.CharField(max_length=55, null=True, blank=True)
def __str__(self):
return f"{self.fio}"
But I got the below message on superAdmin Panel:
TypeError at /admin/api/benefactor/
create_reverse_many_to_one_manager.\<locals\>.RelatedManager.__call__() missing 1 required keyword-only argument: 'manager'
I would expect delete smoothly!!
Your Benefactor model has several ForeignKey relationships that share the related_name. Give each a unique name and rerun your migrations.

django - relation between server tags, server and the post

I'm creating a reddit clone app, There are 3 servers, each server has its own set of tags(e.g., for food server: burger, pizza,...)
and each server can have multiple posts(just like Reddit).
so how can I make it so that the user can choose between tags when creating a new post?
user should only be able to choose on of the tags dedicated to the server which the post is going to be posted on.
I've made a ServerTag model to save tags when creating a new server:
class ServerTag(models.Model):
server = models.ForeignKey(Server, on_delete=models.CASCADE, related_name='tags')
name = models.CharField(max_length=20)
primary_color = ColorField(default = '#ffff')
secondary_color = ColorField(default = '#ffff')
is_allowed = models.BooleanField(default=True)
def __str__(self) -> str:
return f'{self.name} --> r/{self.server}'
Server model:
class Server(models.Model):
creator = models.ForeignKey(User , on_delete=models.CASCADE)
created = models.DateTimeField(auto_now=True)
name = models.CharField(max_length=50)
about = models.TextField(default='about')
tag = models.CharField(max_length=50)
slug = models.SlugField(default='server')
image = models.ImageField(upload_to='servers/pic/')
header_image = models.ImageField(upload_to='servers/header-pic/')
members_count = models.IntegerField(default=0)
online_count = models.IntegerField(default=0)
required_karma = models.IntegerField(default=0)
def __str__(self):
return self.name
and Post Model:
class Post(models.Model):
post_type_choices = [('text', 'text'), ('video', 'video'), ('image', 'image'), ('link','link')]
title = models.CharField(max_length=200)
slug = models.SlugField(max_length=50, default='slug')
text = models.TextField(null=True, blank=True)
text_allowed = models.BooleanField(default=True)
image = models.ImageField(upload_to='posts/images/', null=True, blank=True)
image_allowed = models.BooleanField(default=True)
video = models.FileField(upload_to='posts/videos/', null=True, blank=True)
video_allowed = models.BooleanField(default=True)
server = models.ForeignKey(Server, on_delete=models.CASCADE, related_name='posts')
creator = models.ForeignKey(User , on_delete=models.CASCADE, related_name='posts', null=True)
created = models.DateTimeField(auto_now=True)
type = models.CharField(max_length=5, choices=post_type_choices, default='text')
votes_count = models.IntegerField(default=0)
tag = models.ForeignKey(ServerTag, on_delete=models.CASCADE , default=1) //connected to the ServerTags model
Currently Post has a tag field which shows all tags created in all servers, Though I only want to show tags dedicated to the server which the user is posting on.

Django: How to check object category when using Model Inheritance?

Here is my models.py the idea of app is to have different objects (restaurants, services, etc) with different features (you can check each Model). But when I want to get all objecs Object.objects.all() I don't know which is the category for each of them.
models.py:
from django.db import models
from users.models import ProfileUser
from django.utils import timezone
# Create your models here.
class City(models.Model):
name = models.CharField(max_length=20)
def __str__(self):
return f"{self.name}"
class Object(models.Model):
author = models.ForeignKey(ProfileUser, on_delete=models.CASCADE)
title = models.CharField(max_length=300)
city = models.ForeignKey(City, on_delete=models.CASCADE)
address = models.CharField(max_length=300)
phone = models.CharField(max_length=20, default='')
email = models.CharField(max_length=100, default='')
site = models.CharField(max_length=100, default='')
facebook = models.CharField(max_length=100, default='')
instagram = models.CharField(max_length=100, default='')
content = models.TextField()
rating = models.IntegerField(default=10)
created_date = models.DateTimeField(default=timezone.now)
approved_object = models.BooleanField(default=False)
admin_seen = models.BooleanField(default=False)
def __str__(self):
return f"{self.title}"
class Restaurant(Object):
seats = models.IntegerField()
bulgarian_kitchen = models.BooleanField(default=False)
italian_kitchen = models.BooleanField(default=False)
french_kitchen = models.BooleanField(default=False)
is_garden = models.BooleanField(default=False)
is_playground = models.BooleanField(default=False)
class SportFitness(Object):
is_fitness_trainer = models.BooleanField(default=False)
class CarService(Object):
is_parts_clients = models.BooleanField(default=False)
class BeautySalon(Object):
is_hair_salon = models.BooleanField(default=False)
is_laser_epilation = models.BooleanField(default=False)
class FastFood(Object):
is_pizza = models.BooleanField(default=False)
is_duner = models.BooleanField(default=False)
is_seats = models.BooleanField(default=False)
class CarWash(Object):
is_external_cleaning = models.BooleanField(default=False)
is_internal_cleaning = models.BooleanField(default=False)
is_engine_cleaning = models.BooleanField(default=False)
class Fun(Object):
is_working_weekend = models.BooleanField(default=False)
is_kids_suitable = models.BooleanField(default=False)
class Other(Object):
is_working_weekend = models.BooleanField(default=False)
class Comment(models.Model):
object = models.ForeignKey(Object, on_delete=models.CASCADE, related_name='comments')
author = models.ForeignKey(ProfileUser, on_delete=models.CASCADE)
content = models.TextField()
rating = models.TextField()
created_date = models.DateTimeField(default=timezone.now)
def __str__(self):
return f"{self.content}"
You can not get the categories using the Object model.
Object class is created for a particular purpose:
it eliminates the need to declare certain characteristics of a class
Here you can use select_related or prefect_related to get the desired output.
OR
To fulfill your requirements you can use django-polymorphic for more detail you can refer the documentation.
This is how I did it:
Based on #wfehr commend and #Lokesh Pathak answer I implemented django-polymorphic, also added two additional rows(columns) to each model (only for Restaurants for now), so when foreach over all object I can print exact name of category, additional fields are
category_en_name = models.CharField(max_length=100, default='restaurants')
category_bg_name = models.CharField(max_length=100, default='Ресторант')
full models.py:
from django.db import models
from users.models import ProfileUser
from django.utils import timezone
from polymorphic.models import PolymorphicModel
# Create your models here.
class City(models.Model):
name = models.CharField(max_length=20)
def __str__(self):
return f"{self.name}"
class Object(PolymorphicModel):
author = models.ForeignKey(ProfileUser, on_delete=models.CASCADE)
title = models.CharField(max_length=300)
city = models.ForeignKey(City, on_delete=models.CASCADE)
address = models.CharField(max_length=300)
phone = models.CharField(max_length=20, default='')
email = models.CharField(max_length=100, default='')
site = models.CharField(max_length=100, default='')
facebook = models.CharField(max_length=100, default='')
instagram = models.CharField(max_length=100, default='')
content = models.TextField()
rating = models.IntegerField(default=10)
created_date = models.DateTimeField(default=timezone.now)
approved_object = models.BooleanField(default=False)
admin_seen = models.BooleanField(default=False)
def __str__(self):
return f"{self.title}"
class Restaurant(Object):
seats = models.IntegerField()
bulgarian_kitchen = models.BooleanField(default=False)
italian_kitchen = models.BooleanField(default=False)
french_kitchen = models.BooleanField(default=False)
category_en_name = models.CharField(max_length=100, default='restaurants')
category_bg_name = models.CharField(max_length=100, default='Ресторант')
is_garden = models.BooleanField(default=False)
is_playground = models.BooleanField(default=False)
class SportFitness(Object):
is_fitness_trainer = models.BooleanField(default=False)
So I can take only Restaurants in views.py:
objects = Object.objects.instance_of(Restaurant)
And in template, I can show category name of each restaurant:
{% for object in objects %}
{{ object.category_bg_name }}
{% endfor %}

Django: many to many circular reference

I have a problem in my models because I have a circular reference in a many to many relationship
This is a part of my web app, the Sessions are of a group (a group can have more than one session) and each Session have more than one assistant but the assistants only can be members of the session's group
Here are my models:
class GroupMember(models.Model):
member = models.ForeignKey(Volunteer, null=True, blank=True)
group = models.ForeignKey(Group)
leader = models.BooleanField(default=False)
created = models.DateTimeField(auto_now_add=True)
def __str__(self):
return '{}'.format(self.member)
class Session(models.Model):
name = models.CharField(max_length=250)
group = models.ForeignKey(Group)
assistants = models.ManyToManyField(GroupMember,through=SessionAssistant)
created = models.DateTimeField(auto_now_add=True)
def __str__(self):
return '{}'.format(self.name)
class SessionAssistant(models.Model):
assistant = models.ForeignKey(GroupMember)
session = models.ForeignKey(Session, null=True, blank=True, on_delete=models.CASCADE)
assist = models.BooleanField(default=True)
ability = models.IntegerField(null=True,
blank=True,
validators=[MaxValueValidator(5), MinValueValidator(1)])
performance = models.IntegerField(null=True,
blank=True,
validators=[MaxValueValidator(5), MinValueValidator(1)])
created = models.DateTimeField(auto_now_add=True)
def __str__(self):
return '{}'.format(self.assistant)
What happens if you change assistants = models.ManyToManyField(GroupMember,through=SessionAssistant) to assistants = models.ManyToManyField(GroupMember,through='SessionAssistant')?

Using one form for two similar models

I have the following models:
class BaseAddress(models.Model):
name = models.CharField(max_length=100)
business_name = models.CharField(max_length=100, blank=True, null=True)
address = models.CharField(max_length=100, blank=True, null=True)
address_2 = models.CharField(max_length=100, blank=True, null=True)
address_3 = models.CharField(max_length=100, blank=True, null=True)
city = models.CharField(max_length=100, blank=True, null=True)
state = models.CharField(max_length=2, blank=True, null=True)
zip_code = models.CharField(max_length=10, blank=True, null=True)
phone = models.CharField(max_length=30, blank=True, null=True)
class Meta:
abstract = True
class ProfileBilling(BaseAddress):
profile = models.OneToOneField(
Profile, related_name='billing_info')
class OrderBilling(BaseAddress):
order = models.OneToOneField(Order, related_name='billing')
name_on_card = models.CharField(max_length=100)
#card_type = models.PositiveSmallIntegerField(
# choices=CARD_TYPE, default=0)
#card_number = models.CharField(
# max_length=16, default=0)
expire_month = models.PositiveSmallIntegerField(
choices=MONTHS, null=True, default=0)
expire_year = models.PositiveSmallIntegerField(
choices=YEARS, null=True, default=1960)
When customers input a billing address, I want to save it in OrderBilling, but I also want to save it in ProfileBilling as their most recent billing address. How do I do so?
How do I go about using forms to save billing address in two different tables when the OrderBilling and ProfileBilling have most of the same fields...?
How do I do this in Django?
Here is my OrderBilling form:
class OrderBillingForm(forms.ModelForm):
class Meta:
model = OrderBilling
exclude = ('order',)
def __init__(self, *args, **kwargs):
super(OrderBillingForm, self).__init__(*args, **kwargs)
self.fields['address'].required = True
self.fields['city'].required = True
self.fields['state'] = USStateField()
self.fields['zip_code'] = us.USZipCodeField()
self.fields['phone'].required = False
self.fields['expire_month'].required = False
self.fields['expire_year'].required = False
def clean(self):
return self.cleaned_data
You can override save() method, But the smarter way in your case would be using post_save signal for this purpose.
After aOrderBilling get saved, You can save its data into ProfileBilling too.
look at some example on google search in case to be familiar with post_save signal,
like:
https://groups.google.com/forum/?fromgroups=#!topic/django-users/2m88qTrqnM8
http://www.djangofoo.com/85/signal-connect-disconnect-django-signals
etc...
then Easyily in your post_save receiver|callback funcstion get the OrderBilling instance
orderbil_instance = kwargs['instance']
And create your ProfileBilling from its data
ProfileBilling.objects.create(name=orderbil_instance.name, ....)
Something like on post_save signal receiver
def do_something(sender, **kwargs):
# Getting OrderBilling instance which get saved just now
orderbil_instance = kwargs['instance']
# Save the data into new ProfileBilling
ProfileBilling.objects.create(name=orderbil_instance.name, ....)

Categories