I have a classic model containing some contact data (mail, addr, names, ...), and an other which is supposed to link to three contacts (an admin, an owner, a tech). A contact can be registered as admin and as tech for example.
class Contact(django.db.models.Model):
user = models.OneToOneField(User)
city = models.CharField(max_length=255, blank=True)
country = models.CharField(max_length=2, blank=True)
email = models.EmailField(max_length=255, blank=True)
first_name = models.CharField(max_length=255, blank=True)
family_name = models.CharField(max_length=255, blank=True)
phone = models.CharField(max_length=255, blank=True)
class Product(... Some parents)
name = models.CharField(max_length=255)
contacts ?
I don't know how to link 3 contacts to my other Model ... and generate a form with a queryset already existing.
Some advices ?
Thanks
just use foreign keys
example:
class Product(... Some parents)
name = models.CharField(max_length=255)
admin = models.ForeignKey(Contact, related_name="admins")
owner = models.ForeignKey(Contact, related_name="owners")
tech = models.ForeignKey(Contact, related_name="techs")
if you want to generate the form use a modelform
class MyForm(forms.ModelForm):
class Meta:
model=Product
the select widgets will be filled automatically
EDIT: to display your contact in a human friendly way use
class Contact(django.db.models.Model):
<usual stuff>
def __unicode__(self):
return u"%s" % self.firstname # or any field you wish
see https://docs.djangoproject.com/en/1.10/ref/models/instances/#str
if you use python 3 replace unicode by str
Related
I'm doing a cookbook app, which help users find meal thay can do with their ingridients. I'm using Django RestFramework, and i need to return list of avaliable meals that user can do, but don't know how to do search by ingridients
My models.py:
#models.py
class Meal(models.Model):
name = models.CharField(max_length=250)
description = models.TextField(blank=True, null=True)
recipe = models.TextField()
is_published = models.BooleanField(default=False)
category = ForeignKey('Category', on_delete=models.CASCADE, null=True)
user = ForeignKey(User, verbose_name='User', on_delete= models.CASCADE)
difficulty = ForeignKey('Difficulty', on_delete=models.PROTECT, null=True)
ingridients = models.ManyToManyField('Ingridient')
class Ingridient(models.Model):
name = models.CharField(max_length=100, db_index=True)
ico = models.ImageField(upload_to="photos/%Y/%m/%d/", blank=True, null=True)
category = ForeignKey('CategoryIngridients', on_delete=models.CASCADE, null=True)
def __str__(self):
return self.name
class CookBookUser(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
ingridients = models.ManyToManyField('Ingridient')
serializer.py
class MealSerializer(serializers.ModelSerializer):
class Meta:
model = Meal
fields = "__all__"
views.py
class CraftWithUsersIngridientsListAPIView(generics.ListAPIView):
serializer_class = MealSerializer
def get_queryset(self):
return Meal.objects.filter(ingridients=CookBookUser.objects.filter(user_id = self.request.user.id).ingridients)
CraftWithUsersIngridientsListAPIView isn't working and I get AttributeError 'QuerySet' object has no attribute 'ingridients', can someone help fix this?
I tried building different serializer but it doesn't help
class CraftWithUsersIngridientsListAPIView(generics.ListAPIView):
serializer_class = MealSerializer
def get_queryset(self):
user_ingredients = CookBookUser.objects.get(user=self.request.user).ingredients.all()
return Meal.objects.filter(ingredients__in=user_ingredients)
This way, you first get the CookBookUser instance for the current user, then get all of their ingredients, and finally, filter the Meal objects that contain those ingredients. The __in query lookup is used to check if the meal ingredients are in the user's ingredients.
I am currently working on a mobile app delivery system which involves two types of users: "Employee" and "Customer". Each type of user would have different views and permissions within the app. In addition, each type of user would their own "profile", if you will. The employee's profile purpose is mostly just to designate company roles. The customer's profile is mostly used to save an address for delivery.
I am trying to get some opinions on what the best practice to achieve something like this would be. I can't decide if its better to use AbstractBaseUser or AbstractUser.
Below is a visual of the models I want to create along with their relationship:
Below is the the user/models.py file that I mocked up:
class User(AbstractBaseUser):
USER_TYPES = (
('Employee', 'employee'),
('Customer', 'customer')
)
first_name = models.CharField(max_length=100)
last_name = models.CharField(max_length=100)
email = models.EmailField()
phone_number = models.CharField(max_length=20)
user_type = models.CharField(max_length=8, choices=USER_TYPES)
def __str__(self):
return f'{self.first_name} {self.last_name}'
# if user.user_type == 'Employee'
class EmployeeProfile(models.Model):
EMPLOYEE_ROLES = (
('Driver', 'driver'),
('Production', 'production'),
('Manager', 'manger')
)
user = models.OneToOneField(User, on_delete=models.CASCADE)
role = models.CharField(max_length=12, choices=EMPLOYEE_ROLES)
def __str__(self):
return self.user
# if user.user_type == 'Customer'
class CustomerProfile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
company = models.CharField(max_length=100)
address = models.CharField(max_length=100)
address_2 = models.CharField(max_length=100)
city = models.CharField(max_length=50)
state = models.CharField(max_length=2, help_text="State Abbreviation (ex: OH)")
zipcode = models.CharField(max_length=5)
def __str__(self):
return self.user
I know that I would also need to use Django signals or something similar to create a User profile (for either an employee or customer, on user creation).
Your code works
But according to the design pattern standards, it can be said to put a Boolianfield in the user named is_employee and all the information of both types of users should be in AbstractUser, but with null=True and blank=True values.
This way you have a single user with which it can be separated by a is_employee field
I hope it was useful
So I have a social media app, where users can like the posts of other users. Now I want to fetch the top 20 users who have received the most number of likes. I am pretty much confused how to query my Likes Model
My LIKES MODEL
class PostLike(models.Model):
user_who_liked = models.ForeignKey(User, on_delete=models.CASCADE)
post_liked = models.ForeignKey(Post, on_delete=models.CASCADE)
liked_on = models.DateTimeField(default=timezone.now)
SIMPLIFIED POST MODEL
class Post(models.Model):
id = models.AutoField(primary_key=True)
user = models.ForeignKey(User, on_delete=models.CASCADE)
caption = models.TextField()
date = models.DateTimeField(default=timezone.now)
likes = models.ManyToManyField(
User, blank=True, through=PostLike)
image = models.TextField()
class Meta:
ordering = ['-id']
SIMPLIFIED USER MODEL
class User(AbstractBaseUser, PermissionsMixin):
email = models.EmailField(unique=True)
user_name = models.CharField(max_length=100, unique=True)
date = models.DateTimeField(default=timezone.now)
profile_picture = models.TextField(
default="https://www.kindpng.com/picc/m/24-248253_user-profile-default-image-png-clipart-png-download.png")
bio = models.CharField(max_length=200, default="")
objects = CustomManger()
def __str__(self):
return self.user_name
** My View **
#api_view(["GET"])
#permission_classes([IsAuthenticated])
def leaderboard(request):
# I dont know how to query the PostLike model now to get the most liked users
pass
First I changed the user attribute in your Post model, I added related_name because otherwise the related names were clashing. This is the definition I used, otherwise your models are unchanged.
user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='author')
I.e. the posts by a user are accessible on User via the author attribute.
The following query gives you the top 20 users by number of likes they received:
User.objects.annotate(num_likes=Count('author__likes')).order_by('-num_likes')[:20]
Explanation:
Query User model and
annotate each user by doing a count:
author leads to the posts by the user
likes follows to PostLike and counts all likes which are associated with a post by the user
then order by number of likes descending,
and limit the number of retrieved objects to 20.
I am attempting to create a food delivery app clone. Which has two types of users Restaurant User and Customers. I want the restaurant user to be able to also be customers, using the same login info.
This is how my models are setup right now:
class Restaurant(models.Model):
user_name = models.OneToOneField(User, on_delete=models.CASCADE, related_name='restaurant')
full_name = models.CharField(max_length=500)
phone = models.CharField(max_length=500)
employee_id = models.CharField(max_length=500)
class Customer(models.Model):
user_name = models.OneToOneField(User, on_delete=models.CASCADE, related_name='customer')
full_name = models.CharField(max_length=500)
email = models.CharField(max_length=500)
avatar = models.CharField(max_length=500)
phone = models.CharField(max_length=500)
address = models.CharField(max_length=500)
I don't believe this works as intended. Would it be better to create a base usertype, for login and shared information, like user_name, full_name, phone?
I created the following for that purpose:
class CustomUser(AbstractUser):
user_name = models.OneToOneField(User, on_delete=models.CASCADE, related_name='CustomUser')
full_name = models.CharField(max_length=500)
phone = models.CharField(max_length=30)
But I'm not sure how to connect this between the other user models. Or if this is even the proper way to do it.
So how can I achieve what I am trying to do, what would my models look like?
This should be helpful https://docs.djangoproject.com/en/3.1/topics/db/models/#model-inheritance
You can use the custom user as the base class. So you could pass that custom model as such:
class Restaurant(CustomUser):
user_name = models.OneToOneField(User, on_delete=models.CASCADE, related_name='restaurant')
full_name = models.CharField(max_length=500)
phone = models.CharField(max_length=500)
employee_id = models.CharField(max_length=500)
class Customer(CustomUser):
user_name = models.OneToOneField(User, on_delete=models.CASCADE, related_name='customer')
full_name = models.CharField(max_length=500)
email = models.CharField(max_length=500)
avatar = models.CharField(max_length=500)
phone = models.CharField(max_length=500)
address = models.CharField(max_length=500)
Also, you should declare the CustomUser as abstract.
class CustomUser(AbstractUser):
user_name = models.OneToOneField(User, on_delete=models.CASCADE,related_name='CustomUser')
full_name = models.CharField(max_length=500)
phone = models.CharField(max_length=30)
class Meta:
abstract = True
Follow this:
class Restaurant(models.Model):
owner = models.ForeignKey(CustomUser, on_delete=models.CASCADE, related_name='restaurant')
name = models.CharField(max_length=500)
address = models.TextField(max_length=500)
phone = models.CharField(max_length=500)
class RestaurantStaff(models.Model):
restaurant = models.ForeignKey(Restaurant, on_delete=models.CASCADE, related_name='staff')
staff = models.ForeignKey(CustomUser, on_delete=models.CASCADE, related_name='staff')
employee_id = models.CharField(max_length=500)
class CustomUser(AbstractUser):
full_name = models.CharField(max_length=500)
email = models.EmailField(unique=True)
avatar = models.CharField(max_length=500)
phone = models.CharField(max_length=500)
address = models.CharField(max_length=500)
Note: Never duplicate the columns, if you inherit the same model in two other model, both of those model will have same fields/columns of the inherited model.
Here is the explaination of model structure:
There is only one CustomUser model that holds the data for all users(customer, restaurant owner, staff)
Restaurant model holds the data related to restaurant(its owner link, name, address, restaurant phone number)
RestaurantStaff model hold the relation of a restaurant and a user(which is the restaurant staff), so there you can add more fields like, "start_date", "termination_date", "post"
Your choice of field types are incorrect(example phone number should be interger, but you choose character, email should be email field, but you choose character). Use what django already provide as it helps in validation and serialization in API.
I'm trying to create an address form with multiple address, where the user can choose home or shipping address. I have the current model:
from django.db import models
from django.contrib.auth.models import User
from PIL import Image
class Address(models.Model):
name = models.CharField(max_length=30)
address = models.CharField(max_length=50)
city = models.CharField(max_length=60, default="Miami")
state = models.CharField(max_length=30, default="Florida")
zipcode = models.CharField(max_length=5, default="33165")
country = models.CharField(max_length=50)
class Meta:
verbose_name = 'Address'
verbose_name_plural = 'Address'
def __str__(self):
return self.name
So I was wondering if that's correct.
Anyway, I was wondering how with the current model I can create a view so I can have the address form. Using a normal model would be "easy" but how can I do it using the through option in the model?
Could someone lend me a hand please?
Thank you
use a foreign key to point to your address model:
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
nick_name = models.CharField('Nick name', max_length=30, blank=True, default='')
bio = models.TextField(max_length=500, blank=True)
image = models.ImageField(default='default.jpg', upload_to='profile_pics')
addresses = models.ForeignKey(Address) # <-- fix here
Hope this helps!
You should declare ForeignKey with '<app>.<model>' format:
class AddressType(models.Model):
address = models.ForeignKey('yourapp.Address', on_delete=models.CASCADE)
profile = models.ForeignKey('yourapp.Profile', on_delete=models.CASCADE)
or directly give the class:
address = models.ForeignKey(Address, on_delete=models.CASCADE)
profile = models.ForeignKey(Profile, on_delete=models.CASCADE)
Both of the other answers were incorrect, I ended up modifying everything and also creating a new model, here it is:
class Address(models.Model):
name = models.CharField(max_length=100, blank=False)
address1 = models.CharField("Address lines 1", max_length=128)
address2 = models.CharField("Address lines 2", max_length=128, blank=True)
city = models.CharField("City", max_length=64)
# state = USStateField("State", default='FL')
state = models.CharField("State", max_length=128, default='FL')
zipcode = models.CharField("Zipcode", max_length=5)
user = models.ForeignKey(Profile, on_delete=models.CASCADE, blank=False)
class Meta:
verbose_name_plural = 'Address'
def __str__(self):
return self.name