I'm trying to keep my project well organized, so I try to keep it splitted to apps.
Assume a blog app with a BlogPost model.
Now I add to that a Tag app, which has a Tag model with foreign key to Post.
Now if I want to write a method get_tags(), in the Blog class, that would be circular reference.
So is that a bad design? Maybe I should not write such method on the blog, or such related models should simply be in the same app?
I'm Simply trying to learn how to organize my (big) project. I've read a lot about django app concept, stil haven't found a right way
The point here is that Django automatically creates reverse lookup when you create a ForeignKey or ManytoManyField. Assuming your models are as follows:
BlogPost Model
from django.db import models
class BlogPost(models.Model):
title = models.CharField(_('title'), max_length=200)
slug = models.SlugField(_('slug'), unique_for_date='publish')
author = models.ForeignKey(User, blank=True, null=True)
body = models.TextField(_('body'), )
publish = models.DateTimeField(_('publish'), default=datetime.datetime.now)
created = models.DateTimeField(_('created'), auto_now_add=True)
Tag Model
from django.db import models
from Blog.models import BlogPost
class Tag(models.Model):
Post = models.ForeignKey(BlogPost,related_name="tags")
Now, assuming you are generating the Tags of a post in a view, you can basically get all the tags of a post by just calling blogpost.tags_set where blogpost is a model instance of BlogPost.
Related
I mostly work with Node.js & MongoDB and I am pretty new to SQL dbs especially postgreSQL I am writing an application that makes use of django-rest-framework & postgreSQL as a DB.
This is how my data structure as .json should look like.
{
id: "19eea956-34e5-11eb-adc1-0242ac120002"
picture: [{
url: "",
mimeType: ""
},
{
url: "",
mimeType: ""
}]
}
For the above data I am currently writing models.py which looks like as follows.
from django.db import models
from django.contrib.postgres.fields import ArrayField
class Picture(models.Model):
url = models.CharField()
mimeType = models.CharField()
class A(models.Model):
id = models.CharField(max_length=120, primary_key=True)
picture = ArrayField(Picture)
def __str__(self):
return self.id
What I am trying to do in my models.py is to have picture as an Array of Objects or in python terminology List of Dictionaries.
I read about ArrayField in postgreSQL but unable to find any example about how to define Array of Objects in models.py, any help here would be appreciated.
Thanks :)
In relational databases relations are defined by Foreign Keys and different tables. Tables are represented by Django's models, but the programmer should work from the model side of things and think of the database as the object persistence (storage of the state of an object).
Fields should as a rule be single values, not containers. Explaining why distracts too much from the problem at hand, but here's the in-depth info.
In this case, you have two entities, let's call A "Gallery" for clarity. A Gallery object has 1 or more pictures. A picture can be associated with 1 gallery (business rule). There are 2 properties associated with the image: url and mime type.
Now there's several ways to deal with images and that depends whether the image is uploaded or really a URL to a remote image.
I'm going to pick the second option for brevity:
import uuid
from django.db import models
class Gallery(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4)
name = models.CharField(max_length=40)
class Picture(models.Model):
url = models.URLField()
mime_type = models.CharField(max_length=25)
gallery = models.ForeignKey(Gallery, on_delete=models.CASCADE, related_name='pictures')
This creates the correct relation for the image in a way that is preferred by both Django and relational databases.
Now we need to serialize the picture to just the url and mime type field:
from rest_framework import serializers
from .models import Picture, Gallery
class PictureSerializer(serializers.ModelSerializer):
class Meta:
model = Picture
fields = ['mime_type', 'url']
Continuing, we need to nest the pictures into the gallery:
class GallerySerializer(serializers.ModelSerializer):
pictures = PictureSerializer(many=True)
class Meta:
model = Gallery
fields = ['id', 'pictures']
And this should do the trick.
The reason people downvoted is most likely because this is a Q&A site and your scope as demonstrated by my answer is far too big for that. I've given you some handles to work with, but it's best you hit the Django tutorial to get a basic sense of models, followed by the DRF counterpart.
Is there anyway where we can build logic Using django rest framework
where user can add blog with multiple images and content accordingly and when saved
and retrieved it should be able to display the same kind of UI depening up on the frontend app
same like medium platform
Note:
My question isn't about adding multiple images and content using Rest framework
but its about fetching and displaying the data based on how user sent it the server
For eg:
<Image>
content for that image
<Image2>
content for this image
i just want to know how to associate those images to that content
i want to add content to that image
or is there anyway where we can store image and all the content exacty and save it in TextField
I've searched a lot about this but unfortunately I've not found a way to make this happen
Read about relationships in Django (and SQL in general)
django relations
it sounds like you're looking for something like the following:
from django.contrib.auth import get_user_model
from django.contrib.auth.models import AbstractUser
from django.db import models
class CustomUser(AbstractUser):
# Always override the user model provided by Django when starting a project. the docs themselves state that.
pass
class Image(models.Model):
image = models.ImageField()
added = models.DateTimeField(auto_now_add=True)
# using get_user_model to get the User model, always better then referencing User directly
user = models.ForeignKey(get_user_model(), on_delete=models.CASCADE, related_name="user_images",
null=False,
blank=False
)
class ImageContent(models.Model):
title = models.CharField(max_length=140, null=False, blank=False)
content = models.TextField(max_length=500)
image = models.OneToOneField(Image, on_delete=models.CASCADE, null=False, blank=False)
Some notes:
I haven't dealt myself with Images field But I remember it does require a special library (pillow).
getting the data in a certain order should be easy enough if you understand the queryset object:
queryset link
using stuff like order_by will help you return the response in the order you like.
the models I've written here are not the only way to achieve the goal you've set, I strongly recommend reading about relations and models in Django.
In Django, I have installed allauth. Then I have created a new app, where user's actions will be. I want to link each of the actions with allauth's user data within EmailAddress model.
My questions are:
Normally, data is defined by user_action = models.CharField(max_length=200) and such. ForeignKey on user action does not allow defining field types, at least from what I've seen. How can I define it, or is it okay not to define it?
How can I define the relationship with data in allauth's model that's not anywhere near this new app? For example, I have:
from django.db import models
import allauth.account.models
class Button(models.Model):
button_one = models.ForeignKey('EmailAddress', on_delete=models.CASCADE)
def __str__(self):
return self.button_one
It does not work. The error shows:
input.Button.comment: (fields.E300) Field defines a relation with model 'EmailAddress', which is either not installed, or is abstract.
input.Button.comment: (fields.E307) The field input.Button.comment was declared with a lazy reference to 'input.emailaddress', but app 'input' doesn't provide model 'emailaddress'.
The allauth model data ("user") in question is:
class EmailAddress(models.Model):
user = models.ForeignKey(allauth_app_settings.USER_MODEL,
verbose_name=_('user'),
on_delete=models.CASCADE)
email = models.EmailField(unique=app_settings.UNIQUE_EMAIL,
max_length=app_settings.EMAIL_MAX_LENGTH,
verbose_name=_('e-mail address'))
verified = models.BooleanField(verbose_name=_('verified'), default=False)
primary = models.BooleanField(verbose_name=_('primary'), default=False)
objects = EmailAddressManager()
I'm using virtualenv and have allauth installed within the project.
So EmailAddress is your User model?
In that case you might be able to do this via the standard way by referring to settings.py
Import . from settings
class Button(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL)
How can I index a field that is managed by the Django Tagging (v0.4.5) TagField manager?
The tags are all working correctly and Watson (v1.2.1) is indexing the models and returning results from searching the char and text fields as it should but not if the search term is a tag.
The registering is done in an AppConfig as documented:
from __future__ import unicode_literals
from django.apps import AppConfig
from watson import search as watson
class TeamConfig(AppConfig):
name = 'team'
def ready(self):
Team = self.get_model("Team")
watson.register(Team, fields=("title_text", "tagline", "description", "tags"))
Member = self.get_model("Member")
watson.register(Member)
and the Team model that has the tag TagField field is all good:
import blahs
...
from watson import search as watson
from tagging.fields import TagField
...
class Team(models.Model):
pub_date = models.DateField('date published', auto_now_add=True)
title_text = models.CharField('Name', max_length=200, blank=False,
...
tags = TagField()
is_active = models.BooleanField('Active?', default=True)
Anyone got any idea how to get the field indexing same as a char or text field please?
Thanks so much
Rich
In the end I ripped out Django Tagging, created my own model of 'tags' simply with a date and a name string and then threw a ManyToMany field in each of the models to be tagged. Needs some extra logic to update that pool of tags but that seems easy enough with a loop to test if tag.name.exists() upon save for the associated models.
Having that simple field type also made Django Material form way easy to add a selector for the static pool of tags too so win win.
Would still like to know if anyone has a way of returning text through a model manager as I've only been learning python and django on/off for a few months and really loving it so want to do things proper like.
Is there a model field that can handle multiple files or multiple images for django? Or is it better to make a ManyToManyField to a separate model containing Images or Files?
I need a solution complete with upload interface in django-admin.
For guys from 2017 and later, there is a special section in Django docs. My personal solution was this (successfully works in admin):
class ProductImageForm(forms.ModelForm):
# this will return only first saved image on save()
image = forms.ImageField(widget=forms.FileInput(attrs={'multiple': True}), required=True)
class Meta:
model = ProductImage
fields = ['image', 'position']
def save(self, *args, **kwargs):
# multiple file upload
# NB: does not respect 'commit' kwarg
file_list = natsorted(self.files.getlist('{}-image'.format(self.prefix)), key=lambda file: file.name)
self.instance.image = file_list[0]
for file in file_list[1:]:
ProductImage.objects.create(
product=self.cleaned_data['product'],
image=file,
position=self.cleaned_data['position'],
)
return super().save(*args, **kwargs)
No there isn't a single field that knows how to store multiple images shipped with Django. Uploaded files are stored as file path strings in the model, so it's essentially a CharField that knows how to be converted to python.
The typical multiple image relationship is built as a separate Image model with an FK pointing to its relevant model, such as ProductImage -> Product.
This setup makes it very easy to add into the django admin as an Inline.
An M2M field would make sense if you it's truly a many to many relationship where say GalleryImages are referenced from 1 or more Gallery objects.
I had to change from having a single file to multiple files in an existing system and after a bit of research ended up using this: https://github.com/bartTC/django-attachments
It should be easy to subclass the model if you want custom methods.
FilerFileField and FilerImageField in one model:
They are subclasses of django.db.models.ForeignKey, so the same rules apply. The only difference is, that there is no need to declare what model we are referencing (it is always filer.models.File for the FilerFileField and filer.models.Image for the FilerImageField).
Simple example models.py:
from django.db import models
from filer.fields.image import FilerImageField
from filer.fields.file import FilerFileField
class Company(models.Model):
name = models.CharField(max_length=255)
logo = FilerImageField(null=True, blank=True)
disclaimer = FilerFileField(null=True, blank=True)
Multiple image file fields on the same model in models.py:
Note: related_name attribute required, it is just like defining a foreign key relationship.
from django.db import models
from filer.fields.image import FilerImageField
class Book(models.Model):
title = models.CharField(max_length=255)
cover = FilerImageField(related_name="book_covers")
back = FilerImageField(related_name="book_backs")
This answer code taken from django-filer document