one to many relationship not showing in admin - python

I was making a post system with two models Post and Image. I want one post to have multiple images
Here is my models
class Post(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4)
content = models.CharField(max_length=150, null=False)
images = models.ManyToOneRel(
field="image", to="Image", field_name="images")
class Image(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4)
image = models.ImageField()
post = models.ForeignKey(
Post, on_delete=models.CASCADE, related_name="images")
When I checked it in admin the images field is not shown.
I am not entirely sure how to use ManyToOneRel in django. So far what I understood is I need my post saved before i can add an image. Is there any other way I can have multiple images for one post

you only want one relation,in my opinion Foriegn key is better
Just try this:-
class Post(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4)
content = models.CharField(max_length=150, null=False)
image=models.ForeignKey(Image,on_delete=models.SET_NULL,null=True)
class Image(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4)
image = models.ImageField()
Note:- 'Foreign-key itself is a Many-To-One Relation'

You are confusing a relation with a model field. If you want to specify a many-to-one relation, you do that with a ForeignKey, not a ManyToOneRel. This should thus look like:
class Post(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4)
content = models.CharField(max_length=150, null=False)
image = models.ForeignKey(to='Image', on_delete=models.CASCADE)!
Likely you are however not interested in a many-to-one relation, but in a one-to-many relation (where one post can contain zero, one, or more Images). In that case the ForeignKey belongs to the Image model, and you thus set this when you create a new Image object in the ModelAdmin:

Related

Django Relations with Models

I try to figure a clever way out for my models.
I have two models where i want the Legend to have 4 different skills(Skill Model), but I cant seem to get the fitting model relation for it
class Skill(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4)
title = models.CharField(max_length=100)
description = models.CharField(max_length=300)
image = models.ImageField(upload_to='skills/', blank=True, null=True)
class Legend(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4)
title = models.CharField(max_length=100)
description = models.CharField(max_length=1000)
image = models.ImageField(upload_to='legends/%Y/', blank=True, null=True)
skill_1 = models.(Skill, on_delete=models.SET_NULL, null=True)
skill_2 = models.OneToOneField(Skill, on_delete=models.SET_NULL, null=True)
skill_3 = models.OneToOneField(Skill, on_delete=models.SET_NULL, null=True)
skill_4 = models.OneToOneField(Skill, on_delete=models.SET_NULL, null=True)
The problem is I cant rly make a OneToOneField because it want´s a related_name for each, which would make No sense here, since they are all skills and I dont want to call for the owner (Legend) of the skill in 4 different ways
I also tried to make a legend field in the Skill model with a foreignkey on the Legend, but that didnt turned out how i wanted it to be.
thanks for the help ^.^
Moving my answer here, so I can format code
So... do it as I've said. Add FK in Skill pointing to Legend. Afterwards in your admin.py create admin class which inherits from StackedInline or TabularInline. Your file should look like this:
from django.contrib import admin
from apps.legends.models import Skill, Legend
class InlineAdminSkill(admin.TabularInline):
model = Skill
extra = 4
max_num = 4
class LegendAdmin(admin.ModelAdmin):
inlines = [InlineAdminSkill]
admin.site.register(Legend, LegendAdmin)
This should resolve problem in admin - your skill will be visible in your admin legend view. Try it out.
In your views in the other hand you just have to add a logic which uses e.g. formsets and enables you adding max 4 skills.

Django Get object if it has foreignkey

I'm creating an article app (in django) where articles can have images. I want to get articles only when they have at least one image. I already tried:
Article.objects.all().annotate(num_extra=Count("Image")).order_by("-num_extra")
But that only returned a sorted queryset starting with the most images and thats not wat I want.
Is there a way to do that?
My models.py
class Article(models.Model):
id = models.CharField(max_length=8, default=None, primary_key=True, blank=True, verbose_name="ID", unique=True, editable=False)
Category = models.ForeignKey(Category, default=None, on_delete=models.CASCADE, verbose_name="Kategorie")
text = models.CharField(max_length=678543)
#And some other fields
class Image(models.Model):
Article = models.ForeignKey(Article, on_delete=models.CASCADE, default=None, verbose_name="Artikel")
authors = models.ManyToManyField(User, verbose_name="Autor", default=None, blank=True)
#And some other fields
You can filter article by which image is not present at Image
Try this:
Article.objects.filter(image__isnull=False)

Add blog posts without category in django 1.11

I want to be able to add some blog posts with categories and some without categories in django. with this models django admin won't let me add blog posts without a category. Thanks.
from django.db import models
from django.db.models import permalink
class Blog(models.Model):
title = models.CharField(max_length=100, unique=True)
slug = models.SlugField(max_length=100, unique=True)
body = models.TextField()
pub_date = models.DateField(db_index=True, auto_now_add=True)
# Many-to-one relationship.
category = models.ForeignKey('blog.Category')
class Category(models.Model):
title = models.CharField(max_length=100)
slug = models.SlugField(max_length=100)
Update your model like this:
category = models.ForeignKey('blog.Category', blank=True, null=True)
blank=True allow forms to have a blank value.
null=True allows a null value in the database.
Edit: here is the documentation

How should I give ForeignKey to model?

How should I give ForeignKey to model?
Now models.py has User&Item table like
from django.db import models
# Create your models here.
class User(models.Model):
user_id = models.CharField(max_length=200)
name_id = models.CharField(max_length=200)
regist_date = models.DateTimeField(auto_now=True)
class Item(models.Model):
user_id = models.CharField(max_length=200)
name = models.CharField(max_length=200)
item_name = models.CharField(max_length=200)
price = models.CharField(max_length=200)
I wanna treat user_id&name_id as Foreing key.User table is parent table,and Item is child one.I think user_id&name_id in Item should have ForeignKey like
class Item(models.Model):
user_id = models.ForeignKey()
name = models.ForeignKey()
However,how should I connect these 2 model is User is parent&Item is child ?How should I write it?
For sure, you have to read that.
Looks like One User -> Many Items.
Its ForeignKey and we have to set it in User model.
class Item(models.Model):
...
class User(models.Model):
...
item = models.ForeignKey(Item)
You can use something like
class Item(models.Model):
user = models.ForeignKey(User, related_name='items')
Accessing user_id from item will be
item.user.user_id
Accessing all items from a user will be
user.items.all()
It's a good idea to read the documentation on the ForeignKey field.
As for your question, you can connect the Item model to the User model like this:
class Item(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
Again, it's a good idea to read the documentation and figure out what exactly you need, such as what to do when a User object is deleted (the on_delete part in my code).

How to use UUID

I am trying to get unique IDs for my Django objects. In Django 1.8 they have the UUIDField. I am unsure how to use this field in order to generate unique IDs for each object in my model.
Here is what I have for the UUIDField
import uuid
from django.db import models
class MyUUIDModel(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
class Person(models.Model):
...
unique_id = MyUUIDModel()
I can reproduce the id for the UUID model, but everytime I do I get the exact same id. For Example:
person = Person.objects.get(some_field = some_thing)
id = person.unique_id.id
id then gives me the same id every time. What is wrong, how do I fix this?
I'm not sure why you've created a UUID model. You can add the uuid field directly to the Person model.
class Person(models.Model):
unique_id = models.UUIDField(default=uuid.uuid4, editable=False, unique=True)
Each person should then have a unique id. If you wanted the uuid to be the primary key, you would do:
class Person(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
Your current code hasn't added a field to the person. It has created a MyUUIDModel instance when you do MyUUIDModel(), and saved it as a class attribute. It doesn't make sense to do that, the MyUUIDModel will be created each time the models.py loads. If you really wanted to use the MyUUIDModel, you could use a ForeignKey. Then each person would link to a different MyUUIDModel instance.
class Person(models.Model):
...
unique_id = models.ForeignKey(MyUUIDModel, unique=True)
However, as I said earlier, the easiest approach is to add the UUID field directly to the person.
You need to use the class you created as a subclass when declaring your Person model like this:
import uuid
from django.db import models
class MyUUIDModel(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
class Person(MyUUIDModel):
...
This way Person becomes a subclass of MyUUIDModel and will inherit its id field definition.
EDIT: Actually I was wrong. It's not possible yet to implement it as DEFAULT_AUTO_FIELD as it has to inherit from IntegerField. Here's the ticket in the django project with feature request to make it possible. Once it's resolved I'll update my answer.
As of Django 3.2, if you want to use uuid as a pk for all your models on a project-wide level, you don't need a generic abstract model anymore. Just define DEFAULT_AUTO_FIELD setting
default value
DEFAULT_AUTO_FIELD = 'django.db.models.AutoField'
so something like this should work
DEFAULT_AUTO_FIELD = 'django.db.models.UUIDField'
Or even better, create your own field.
DEFAULT_AUTO_FIELD = 'project.common.models.CustomUUIDField'
Where you also define uuid type etc.
As seen in the docs, it can also be applied on an app level.
class MyAppConfig(AppConfig):
default_auto_field = 'project.common.models.CustomUUIDField'
You can directly add the id field as a UUIDField in the Person model. There is no need for a separate MyUUIDModel.
I think you have confused it with the MyUUIDModel used in the UUIDField example where the id is a UUIDField. You can just use the below code and it will use UUIDs for id.
import uuid
from django.db import models
class Person(models.Model):
...
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
To use UUID in Django for a new model see Django Docs.
However, if you want to use it for the existing model (with unique=True) having data corresponding to it, you will not be able to do it directly by the above documentation. It will create migration errors.
To do it without losing the data follow all the steps carefully of this Django Documentation.
in model import uuid:
import uuid
in class model use:
class Article(TimeStampedModel):
uuid = models.UUIDField(editable=False, default=uuid.uuid4, unique=True)
user = models.ForeignKey(User, on_delete=models.SET_NULL, related_name='articles', null=True)
categories = models.ManyToManyField(ArticleCategory, blank=True)
title = models.CharField(max_length=500, null=True, blank=True)
body = RichTextUploadingField(config_name='portal_lobar_config')
image = models.ImageField(upload_to='article_images/', null=True, blank=True)
headline = models.BooleanField(default=True)
tags = models.ManyToManyField(ArticleTag, blank=True)
slug = AutoSlugField(max_length=500, populate_from='title', unique_with='created__month', null=True)
published = models.BooleanField(default=False)
published_at = models.DateTimeField(null=True, blank=True)
def __str__(self):
return self.title
class Meta:
ordering = ['-created']

Categories