I am trying to learn Django by creating something similar to Reddit. I have models for Post and User, and now I want to create one for "Community". I have looked at this post:
How to store an array of users in django?
However, I am unsure if the ManyToMany relationship is right here (perhaps it is).
I want the Community Model to contain Posts and Users registered with the Community. Each Community can have many posts, and each user can belong to multiple communities. When a Community is deleted, only delete the posts in that community, not the users. Similarly, when a User is deleted or a Post deleted, just remove that aspect from the Community.
If anyone has done this before or knows of a resource to learn this please let me know.
Here is my Post model so far. Note my Communities are called "Bands". Thus all of my references to "Community" will be "Bands" in my project.
from django.db import models
from django.utils import timezone
from django.contrib.auth.models import User
# each class is its own table in the data
class Post(models.Model):
# each attribute is a different field in the data
title = models.CharField(max_length=100)
content = models.TextField()
# pass in the function as the default val, but do NOT execute yet!
date_posted = models.DateTimeField(default=timezone.now)
# foreign keys link two tables together
# on delete of User, we delete the user's post as well
author = models.ForeignKey(User, on_delete=models.CASCADE)
def __str__(self):
return self.title
Here is my Band model:
from django.db import models
from django.utils import timezone
from django.contrib.auth.models import User
from home.models import Post
class Band(models.Model):
name = models.CharField(max_length = 100)
date_created = models.DateTimeField(default=timezone.now)
users = (settings.AUTH_USER_MODEL)
def __str__(self):
return "{self.name}"
Related
I have two models: Product and User
class Product(models.Model):
#here are information fields about Product
likes = models.ManyToManyField(
User, related_name="product_likes", blank=True)
object = models.Manager()
productobjects = ProductObjects()
def __str__(self):
return self.name
class User(AbstractBaseUser, PermissionsMixin):
#here are information fields about User
followed = models.ManyToManyField(
Product, related_name="followed_products", blank=True)
objects = CustomAccountManager()
object = models.Manager()
def __str__(self):
return self.email
Inside Product I need to have a likes filed ManyToMany which store which users liked the product. Inside User I need to have followed field ManyToMany which store which products the user follow.
I have an error: cannot import name 'Product' from partially initialized module 'product.models' (most likely due to a circular import). How can I fix it? Or maybe can I do this differently?
I think the problem is that inside product.models I import: from users.models import User and inside users.models I import: from product.models import Product.
(I am using the likes filed just to GET number of likes, but from followed I need to GET all the products that specified user follow and informations about them)
Your Product model needs to import the User model and vice versa. As a result the imports got stuck in an infinite loop.
You can however use a string literal to specify to what model your ManyToManyField is pointing. For example:
# no import of the models module where you define User
class Product(models.Model):
#here are information fields about Product
likes = models.ManyToManyField(
'app_name.User', related_name="product_likes", blank=True
)
# ⋮
Here app_name is the name of the app where you defined the (custom) user model.
Since it is (likely) the user model, you here can use the AUTH_USER_MODEL setting [Django-doc]:
# no import of the models module where you define User
from django.conf import settings
class Product(models.Model):
#here are information fields about Product
likes = models.ManyToManyField(
settings.AUTH_USER_MODEL, related_name="product_likes", blank=True
)
# ⋮
I have a Django Rest Framework project, users can post,comment any post and like any post. I can't figure it out the logic in models.py
from django.db import models
from django.contrib.auth.models import User
class Post(models.Model):
title = models.CharField(max_length=100)
body = models.CharField(max_length=100)
post_author = models.ForeignKey(User,on_delete=models.CASCADE,related_name='posts')
def __str__(self):
return self.title
class Comment(models.Model):
body=models.CharField(max_length=100)
commet_post = models.ForeignKey(Post,on_delete=models.CASCADE,related_name='comments')
comment_author = models.ForeignKey(User,on_delete=models.CASCADE)
def __str__(self):
return self.body
class Like(models.Model):
like_post = models.ForeignKey(Post,on_delete=models.CASCADE)
like_author=models.ForeignKey(User,on_delete=models.CASCADE)
created = models.DateTimeField(auto_now_add=True)
You could make two endpoints for like: 1) for create & 2) for delete. Whenever someone clicks on the like button, it will hit the create endpoint and create a Like object. When someone clicks on unlike, it will hit the delete endpoint and delete the object. Like model will have a one-to-one relationship with User and Post model. You can count likes by a query such as: Like.objects.filter(like_post=post.id).aggregate(Count('pk'))
In a Django web app, let's say there is a prediction cast by the user Daniel. In the prediction, there is an accept button, any User can accept this prediction.
What I want to know is that if User Andrew accepts the offer, how can I store that in Daniel's prediction class? (If there is an accepted_by field in Daniel's prediction class, how can I change that field to Andrew, the actual User object not just a string, when User Andrew accepts that prediction)?
Thanks
In my models.py
from django.db import models
from django.contrib.auth.models import User
from django.urls import reverse
class gamble(models.Model):
prediction = models.BooleanField()
placement = models.PositiveIntegerField()
author = models.ForeignKey(User, on_delete = models.CASCADE)
accepted_by = models. **# this is what I need help with**
date_posted = models.DateTimeField(auto_now_add = True)
def get_absolute_url(self):
return reverse('page-home')
i'm poor with django.
i have a project and project has an app
in my app, i have a models.py and includes
from django.db import models
from taggit.managers import TaggableManager
class Post(models.Model):
title = models.CharField(max_length=100)
body = models.TextField()
created = models.DateTimeField()
tags = TaggableManager()
def __unicode__(self):
return self.title
and i also add this models.py
posts = Post.objects.all().order_by("-created")[:2]
Is it the right way to keep it here?
Some examples shows that queries in models.py some are in views.py ?
Also can i use posts in my mysite/templates ?
The best way to do this is to create a custom manager with a method that performs the query when called. That way you don't need to worry about it being cached, recycled, etc.
Let's say I'm using the default auth.models.User plus my custom Profile and Address models which look like this:
class Profile(models.Model):
user = models.OneToOneField(User)
primary_phone = models.CharField(max_length=20)
address = models.ForeignKey("Address")
class Address(models.Model):
country = CountryField(default='CA')
province = CAProvinceField(default='BC')
city = models.CharField(max_length=80)
postal_code = models.CharField(max_length=6)
street1 = models.CharField(max_length=80)
street2 = models.CharField(max_length=80, blank=True, null=True)
street3 = models.CharField(max_length=80, blank=True, null=True)
Now I want to create a registration form. I could create a ModelForm based on User but that won't include fields for the Profile and Address (which are required). So what's the best way to go about building this form? Should I even use ModelForm at all?
Furthermore, how would I use the same form for editing the complex object? I could easily pass an instance of Profile back to it, which holds references to the necessary Address and Profile objects, but how do I get it to fill in the fields for me?
What about using 3 separate ModelForm. One for Address, one for User, and one for Profile but with :
class ProfileForm(ModelForm):
class Meta:
model = Profile
exclude = ('user', 'address',)
Then, process these 3 forms separately in your views. Specifically, for the ProfileForm use save with commit=False to update user and address field on the instance :
# ...
profile_form = ProfileForm(request.POST)
if profile_form.is_valid():
profile = profile_form.save(commit=False)
# `user` and `address` have been created previously
# by saving the other forms
profile.user = user
profile.address = address
Don't hesitate to use transactions here to be sure rows get inserted only when the 3 forms are valid.
You should look into the officially recommended way to extend the User model first, as seen in the docs, which I believe comes directly from the project manager's personal blog about the subject. (The actual blog article is rather old, now)
As for your actual issue with forms, have a look at the project manager's own reusable django-profiles app and see if perusing the code solves your issue. Specifically these functions and the views in which they are utilized.
Edited to Add:
I've looked into it a bit (as I needed to do so myself). It seems something like so would be sufficient:
# apps.profiles.models
from django.db import models
from django.contrib.auth.models import User
class UserProfile(models.Model):
user = models.ForeignKey(User, unique=True)
...
birth_date = models.DateField(blank=True, null=True)
joined = models.DateTimeField(auto_now_add=True)
modified = models.DateTimeField(auto_now=True)
class Meta:
verbose_name = 'user profile'
verbose_name_plural = 'user profiles'
db_table = 'user_profiles'
class Address(models.Model):
user = models.ForeignKey(UserProfile)
...
# apps.profiles.forms
from django import forms
from django.forms import ModelForm
from django.forms.models import inlineformset_factory
from django.contrib.auth.models import User
from apps.profiles.models import UserProfile, Address
class UserForm(ModelForm):
class Meta:
model = User
...
class UserProfileForm(ModelForm):
class Meta:
model = UserProfile
...
AddressFormSet = inlineformset_factory(UserProfile, Address)
I was using "..." to snip content in the code above. I have not yet tested this out but from looking through examples and the documentation on forms I believe this to be correct.
Note I put the FK from the Address model to the UserProfile and not the other way around, as in your question. I believe the inline formsets need this to work correctly.
Then of course in your views and templates you will end up treating UserForm, UserProfileForm, and AddressFormSet separately but they can all be inserted into the same form.
I think your are looking for inline formsets with model forms. This helps you to deal with multiple forms on one page and also takes care of foreign key relations.
Update:
Maybe this question helps you too: Django: multiple models in one template using forms