I am doing a many to one relationship but I get a prompt that the field person in the report is without a default.
I tried setting the default to an empty space, I get an IntegrityError: NOT NULL constraint failed
class Person(models.Model):
person_name = models.CharField(max_length=255)
person_location = models.CharField(max_length=255, null=True)
classReport (models.Model):
person = models.ForeignKey(
Person, related_name='people', default="", on_delete=models.CASCADE)
product_name = models.CharField(max_length=255)
product_description = models.CharField(max_length=255)
Related
I have this model that records data in slug. The user has a relation with the award model. What am trying to do is list all login user's awards slug field data in the contain filter so i can use it to filter user's data.
NOTE : All the data in save in the SuccessfulTransactionHistory model field award is in slug format and SuccessfulTransactionHistory model has no foreign key relation to award and user
models.py
class Award(models.Model):
admin = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
name = models.CharField(max_length=100)
image = models.ImageField(upload_to='award_images')
slug = models.SlugField(max_length=150, blank=True, null=True)
about_the_award = models.TextField(blank=True, null=True)
status = models.CharField(max_length=20, choices=STATUS_PUBLISHED, default='Closed')
price = models.DecimalField(max_digits=3, default='0.5', decimal_places=1, blank=True, null=True, validators = [MinValueValidator(0.1)])
bulk_voting = models.CharField(max_length=20, choices=BULK_VOTING, default='Closed')
amount = models.DecimalField(default=0.0, max_digits=19, decimal_places=2, blank=True,)
results_status = models.CharField(max_length=20, choices=RESULTS_PUBLISHED, default='private')
starting_date = models.DateTimeField()
ending_date = models.DateTimeField()
date = models.DateTimeField(auto_now_add=True)
class SuccessfulTransactionHistory(models.Model):
nominee_name = models.CharField(max_length=120)
transaction_id = models.CharField(max_length=120)
award = models.CharField(max_length=120)
amount = models.DecimalField(default=0.0, max_digits=19, decimal_places=2)
status = models.CharField(max_length=120, null=True, blank=True)
phone = models.CharField(max_length=120, null=True, blank=True)
date = models.DateTimeField(auto_now_add=True)
In my view.py
success_list = SuccessfulTransactionHistory.objects.filter(award__contains=request.user.award.slug).order_by('-date')
This is my error
'User' object has no attribute 'award'
``
Your User object has a lot of awards, because you use ForeignKey.
The relation is: One award has one User, but One user has one or more than one awards (award_set is the property name).
Solutions? Yes, of course,but depends on the context.
1- If the user has only one award, you can use OneToOneField, and your logic is ok.
2- If the user can have more than one Award, may be you need 2 steps.
Step 1: get all award slugs:
award_slugs = list(request.user.award_set.values_list('slug', flat=True))
where award_slugs is a list of slugs.
Step 2: Get success_list:
success_list = SuccessfulTransactionHistory.objects.filter(award__in=award_slugs)
I have the following related data models
class Cart(models.Model):
products = models.ManyToManyField('assortment.Product', through='CartProduct')
order = models.OneToOneField('Order', on_delete=models.CASCADE, related_name='order_cart', null=True)
user = models.ForeignKey('account.Profile', on_delete=models.CASCADE, related_name='user_carts', blank=True, null=True)
class CartProduct(models.Model):
product = models.ForeignKey('assortment.Product', related_name='product_cartproducts', null=True, on_delete=models.SET_NULL)
cart = models.ForeignKey('Cart', related_name='cart_cartproducts', null=True, on_delete=models.SET_NULL)
count = models.IntegerField(blank=False, null=False, default=1)
class Order(models.Model):
pay_date = models.DateField(auto_now_add=True)
is_paid = models.BooleanField(default=False)
My code below gives an error: invalid argument "products" in prefetch_related:
Order.objects.all().select_related('order_cart').prefetch_related('products')
How can I join all three models in one request?
The query builder continues with the original table (Order), thus you have to specify the fields relative to that or relative to the previously mentioned field. Try one of the following:
'order_cart__products'
'order_cart__cart_cartproducts'
(Notice the double underscore.)
at the moment I try to get recipes from my API. I have a Database with two tables one is with recipes and their ids but without the ingredients, the other table contains the ingredients and also the recipe id. Now I cant find a way that the API "combines" those. Maybe its because I added in my ingredient model to the recipe id the related name, but I had to do this because otherwise, this error occurred:
ERRORS:
recipes.Ingredients.recipeid: (fields.E303) Reverse query name for 'Ingredients.recipeid' clashes with field name 'Recipe.ingredients'.
HINT: Rename field 'Recipe.ingredients', or add/change a related_name argument to the definition for field 'Ingredients.recipeid'.
Models
from django.db import models
class Ingredients(models.Model):
ingredientid = models.AutoField(db_column='IngredientID', primary_key=True, blank=True)
recipeid = models.ForeignKey('Recipe', models.DO_NOTHING, db_column='recipeid', blank=True, null=True, related_name='+')
amount = models.CharField(blank=True, null=True, max_length=100)
unit = models.CharField(blank=True, null=True, max_length=100)
unit2 = models.CharField(blank=True, null=True, max_length=100)
ingredient = models.CharField(db_column='Ingredient', blank=True, null=True, max_length=255)
class Meta:
managed = False
db_table = 'Ingredients'
class Recipe(models.Model):
recipeid = models.AutoField(db_column='RecipeID', primary_key=True, blank=True) # Field name made lowercase.
title = models.CharField(db_column='Title', blank=True, null=True, max_length=255) # Field name made lowercase.
preperation = models.TextField(db_column='Preperation', blank=True, null=True) # Field name made lowercase.
images = models.CharField(db_column='Images', blank=True, null=True, max_length=255) # Field name made lowercase.
#ingredients = models.ManyToManyField(Ingredients)
ingredients = models.ManyToManyField(Ingredients, related_name='recipes')
class Meta:
managed = True
db_table = 'Recipes'
When there is no issue it has to be in the serializer or in the view.
Serializer
class IngredientsSerializer(serializers.ModelSerializer):
# ingredients = serializers.CharField(source='ingredients__ingredients')
class Meta:
model = Ingredients
fields = ['ingredient','recipeid']
class FullRecipeSerializer(serializers.ModelSerializer):
ingredients = IngredientsSerializer(many=True)
class Meta:
model = Recipe
fields = ['title','ingredients']
View
class FullRecipesView(generics.ListCreateAPIView):
serializer_class = FullRecipeSerializer
permission_classes = [
permissions.AllowAny
]
queryset = Recipe.objects.all()
This is at the moment my output
But I want e.g. the recipe with id 0 and all the ingredients which have also recipe id 0.
I really hope that you can help me. Thank you so much!
Rename ingredients to some other name in FullRecipeSerializer. It conflicts with ingredients in Recipe model. This should solve your issue. For example
class FullRecipeSerializer(serializers.ModelSerializer):
ingredients_recipe = IngredientsSerializer(many=True, source= 'ingredientid')
class Meta:
model = Recipe
fields = ['title','ingredients_recipe']
I am trying to create a one to one reference and want to make sure that that reference is not allowed to be used for another model or instance.
For example
Say I have an address model, Person Model and Company Model
Person has a OneToOneField field to Address
Company also has a OneToOneField field to Address
address=Address(data="some address")
company=Company(name="some company",address=address)
person=Person(name="my name",address=address)
Models:
class Address(models.Model):
data = models.CharField(max_length=255, blank=True, null=True)
class Company(models.Model):
name = models.CharField(max_length=255, blank=True, null=True)
address=models.OneToOneField(Address,on_delete=models.CASCADE)
class Person(models.Model):
name = models.CharField(max_length=255, blank=True, null=True)
address=models.OneToOneField(Address,on_delete=models.CASCADE)
I would like the system to throw an error on this since I am setting the same address to 2 different models.
Also this would delete both person and company if I delete address.
Usually you catch this with code and not make a stupid mistake like this.
But can system catch it since it is one to one ?
In the case of the deletion you could use on_delete=models.PROTECT. In the other case you could add unique=True so a person id = 1 will have a address id = 1, a person id = 2 can't have a address id = 1 anymore. But it would only solve for one model:
address=models.ForeignKey(Address, unique=True, on_delete=models.PROTECT)
A new approach would be create a model to reference the address of both company and person and be able to forbid the creation with the same address id:
class AddressExample(models.Model):
id_address = models.ForeignKey(Address, unique=True,on_delete=models.PROTECT)
id_person = models.ForeignKey(Person, blank=True, null=True, unique=True, on_delete=models.PROTECT)
id_company = models.ForeignKey(Person, blank=True, null=True, unique=True, on_delete=models.PROTECT)
Note that I used blank=True, null=True so you can create an instance only with a Person or a Company, without the need to create a instance with both. There is a Meta to use combination of primary keys too.
class AddressExample(models.Model):
id_address = models.ForeignKey(Address, unique=True,on_delete=models.PROTECT)
id_person = models.ForeignKey(Person, blank=True, null=True, unique=True, on_delete=models.PROTECT)
id_company = models.ForeignKey(Person, blank=True, null=True, unique=True, on_delete=models.PROTECT)
class Meta:
unique_togther = ('id_address', 'id_person', 'id_company')
# Not sure if it will throw a error here because `id_person` and `id_company` can be blank
# or null. But the use of `unique together` is for cases where you want to guarantee
# the combination of the primary keys will be unique.
Hope it helps.
I'm kind of new to Django and am having some trouble pulling from existing tables. I'm trying to pull data from columns on multiple joined tables. I did find a solution, but it feels a bit like cheating and am wondering if my method below is considered proper or not.
class Sig(models.Model):
sig_id = models.IntegerField(primary_key=True)
parent = models.ForeignKey('self')
state = models.CharField(max_length=2, db_column='state')
release_id = models.SmallIntegerField(choices=releaseChoices)
name = models.CharField(max_length=255)
address = models.CharField(max_length=255, blank=True)
city = models.CharField(max_length=255, blank=True)
zip = models.CharField(max_length=10, blank=True)
phone1 = models.CharField(max_length=255, blank=True)
fax = models.CharField(max_length=255, blank=True)
email = models.EmailField(max_length=255, blank=True)
url = models.URLField(max_length=255, blank=True)
description = models.TextField(blank=True)
contactname = models.CharField(max_length=255, blank=True)
phone2 = models.CharField(max_length=255, blank=True)
ratinggroup = models.BooleanField()
state_id = models.ForeignKey(State, db_column='state_id')
usesigrating = models.BooleanField()
major = models.BooleanField()
class Meta:
db_table = u'sig'
class SigCategory(models.Model):
sig_category_id = models.IntegerField(primary_key=True)
sig = models.ForeignKey(Sig, related_name='sigcategory')
category = models.ForeignKey(Category)
class Meta:
db_table = u'sig_category'
class Category(models.Model):
category_id = models.SmallIntegerField(primary_key=True)
name = models.CharField(max_length=255)
release_id = models.SmallIntegerField()
class Meta:
db_table = u'category'
Then, this was my solution, which works, but doesn't quite feel right:
sigs = Sig.objects.only('sig_id', 'name').extra(
select = {
'category': 'category.name',
},
).filter(
sigcategory__category__category_id = categoryId,
state_id = stateId
).order_by('sigcategory__category__name', 'name')
Now since the items in filter() join the sigcategory and category models, I was able to pull category.name out by using extra(). Is this a proper way of doing this? What if I did not have the reference in filter() and the join did not take place?
SigCategory has a ForeignKey pointing at Category, so you can always get from the SigCategory to the Category simply by doing mysigcategory.category (where mysigcategory is your instance of SigCategory.
If you haven't previously accessed that relationship from that instance, doing it here will cause an extra database lookup - if you're concerned about db efficiency, look into select_related.