Tried databse queryset on crontab but it doesn't work - python

Crontab works fine on simple task.
e.g
def test():
test.objects.create.(name='Dino')
#It also works on this
def test_task()
if Users_Machine.objects.filter().exists():
test.objects.create(name='Dino')
but when i tried to query my db with foreignkey it does nothing.
Have tried this two methods:
#request method
def test_task(request):
if Users_Machine.objects.filter(user=request.user).exists():
test.objects.create(name='Dino', user=request.user)
#direct methods
def test_task()
if Users_Machine.objects.filter().exists():
name=Users_Machine.objects.get()
test.objects.create(name='Dino', user=name.username)
The Users_Machine.object returns True
Here is my models
#users_machine model
class Users_Machine(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
Name = models.CharField(max_length=20)
#test model
class test(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
name = models.CharField(max_length=100)
Please how can i make this work?

It would be better if I get to look at User model but for now I am going to assume in the request, you are passing Name field which is present in the UserMachine model and you can create new object in test model as follows:
def test_task(request):
Current_user = User_Machine.objects.get(Name = request.name)
if Current_user:
test.objects.create(name='Dino', user=Current_user)
Can you please add User model as well, that will allow me fine tune the answer (or correct it if this one is wrong)?

Related

Unittest a Django model Clean method

I'm working on a simple Django social media project and I'm trying to create a unittest to verify that a User cannot like a post that they created. I want to do one of the following
Write a unittest to test a clean method of a model
or
Write a CheckConstraint to prevent a User and Post creator from being the same Can't create a Check on a related model - https://forum.djangoproject.com/t/checkconstraint-involving-related-model/5351
My Model
In my model I have a UniqueConstraint to prevent a user from liking a post more than once. I initially tried to create a CheckConstraint to prevent a user from like their own post, but couldn't figure out how to do that. An alternative I came upon was to create a clean method that achieved the same goal.
# From models.py
class Post(models.Model):
creator = models.ForeignKey(User, on_delete=models.CASCADE, related_name="creator")
content = models.CharField(max_length=160)
pub_date = models.DateTimeField('date posted', default=timezone.now)
class Like(models.Model):
post = models.ForeignKey(Post, on_delete=models.CASCADE, related_name="likes")
user = models.ForeignKey(User, on_delete=models.CASCADE)
like_unlike = models.BooleanField(choices=BOOL_CHOICES)
def clean(self):
"""Prevent User from liking/unliking their own post"""
if self.user == self.post.creator:
raise ValidationError(_("User cannot like/unlike their own post"))
class Meta:
constraints = [
# Prevent a user from liking/unliking the same post twice
models.UniqueConstraint(fields=['user', 'post'], name="unique like"),
]
My Unittests
When creating my unittests I have been able to test the unique constraint but unable to successfully test the clean method. My expectation was that when I attempt to create a Like entry with a User the same as the Post creator that I would raise an error. I used Like.objects.create
and when that didn't work, tried assigning Like() to a variable and assigned it's values before calling save on it. However both ways seem to bypasses the clean method when it saves to the databases.
# From test_models.py
class LikeTestCase(TestCase):
def setUp(self) -> None:
User.objects.create(username="john", email="john#email.com")
user = User.objects.create(username="mary", email="mary#email.com")
Post.objects.create(creator=user, content=f"post-1", pub_date=timezone.now())
def test_cannot_like_post_multiple_times(self):
"""Verify user cannot like a post more than once"""
post = Post.objects.get(id=1)
user = User.objects.get(name="john")
Like.objects.create(post=post, user=user, like_unlike=True)
with self.assertRaises(IntegrityError):
Like.objects.create(post=post, user=user, like_unlike=True)
def test_cannot_like_own_post_1(self):
"""Verify user cannot like their own post"""
post = Post.objects.get(id=1)
like = Like()
like = Like.objects(post=post, user=post.creator, like_unlike=True)
like.save()
def test_cannot_like_own_post_2(self):
"""Verify user cannot like their own post"""
post = Post.objects.get(id=1)
Like.objects.create(post=post, user=post.creator, like_unlike=True)
From this previous answer the key was to call full_clean() on the model object. My test then became
def test_cannot_like_own_post(self):
"""Verify user cannot like their own post"""
post = Post.objects.get(id=1)
with self.assertRaises(ValidationError):
like = Like(post=post, user=post.creator, like_unlike=True)
like.full_clean()

How to access User Profile's friends in ManyToMany field

I am building a simple social media app. AND i am trying to build a feature of adding users into post using ManyToManyField.
I am trying to access profile friends in Post's model instance "add_user" for tagging user.
models.py
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE,default='',unique=True)
full_name = models.CharField(max_length=100,default='')
friends = models.ManyToManyField("Profile",blank=True)
class Post(models.Model):
post_owner = models.ForeignKey(User,default='',null=True,on_delete = models.CASCADE)
post_title = models.CharField(max_length=500,default='')
add_user = models.ManyToManyField(User.profile.friends.all())
I am new in django and I have no idea how can i access user's friend in Post's model instance.
Any help would be much Appreciated.
Thank You in Advance.
You can't give a queryset as an argument for a ManyToManyField, just a class name.
add_users = models.ManyToManyField(User.profile.friends.all()) # you can't do this.
add_users = models.ManyToManyField(User) # Do this.
You shouldn't place you logic in your model's definition.
Do that in your views.
EDIT:
I suggest you use a ModelChoiceField and do the filtering logic there:
class AddFriendForm(forms.Form):
def __init__(self, *args, **kwargs):
try:
user = kwargs.pop('user')
except:
user = None
super(AddFriendForm, self).__init__(*args, **kwargs)
self.fields['friend'].queryset = user.profile.friends.all()
friend = forms.ModelChoiceField(queryset=User.objects.none())
And then in your view you initialize it like this:
def your_view(request):
form = AddFriendForm(user=request.user)
You cannot do
add_users = models.ManyToManyField(User.profile.friends.all())`
Because the models is evaluated once, and need to be non mutable values
You need to do :
add_user = models.ManyToManyField("Profile",blank=True)
And dont forget to add on your ManyToManyField:
related_name="XXX", null=True

User Follower model on Django. Cannot use add() on a ManyToManyField which specifies an intermediary model. Use accounts.Contact's Manager instead

I am new to Django, Please forgive any silly mistakes in code or logic,
Intro: I am trying to create a user follower model in Django. Where users can follow and unfollow other users on the sites
Error: I have made the models for my follow/unfollow I have also made the views I am getting this error
AttributeError at /accounts/admin/follow/
Cannot use add() on a ManyToManyField which specifies an intermediary model. Use accounts.Contact's Manager instead.
The obj.followers.add(user) is highlighted in the traceback as the origin of the error
Below are my models.py
from django.contrib.auth.models import User
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
city = models.CharField(max_length=100)
country = models.CharField(max_length=100)
def get_absolute_url(self):
return reverse('accounts:profile', kwargs={'username': self.user.username})
class Contact(models.Model):
user_from = models.ForeignKey(User, related_name='suppporter')
user_to = models.ForeignKey(User, related_name='leader')
def __str__(self):
return '{} follows {}'.format(self.user_from, self.user_to)
User.add_to_class('following',
models.ManyToManyField('self', through=Contact, related_name='followers', symmetrical=False))
I think the models.py may be good. The fault I believe is in my views.
Below is my view.py
class FollowToggle(LoginRequiredMixin, RedirectView):
def get_redirect_url(self, *args, **kwargs):
username = self.kwargs.get('username')
print(username + " This is the user who will be followed") # This prints correct
profile = get_object_or_404(Profile, user__username=username)
print(profile) # This prints correct
obj = get_object_or_404(User, username=username)
print(obj) # This prints correct
url_ = profile.get_absolute_url()
print(url_) # This prints correct
user = self.request.user
print(user) # This prints correct
if user.is_authenticated():
if user in obj.followers.all(): # I know this is the source of the error.
obj.followers.remove(user)
else:
obj.followers.add(user)
return url_
Below are the Urls.py just in case
url(r'^(?P<username>[-\w]+)/follow/$', views.FollowToggle.as_view(), name='follow'),
You cannot use add and remove method for manytomany relation defined through third model. From the docs:
Unlike normal many-to-many fields, you can’t use add(), create(), or set() to create relationships
Instead you should use Contact manager:
if user.is_authenticated():
if user in obj.followers.all(): # I know this is the source of the error.
Contact.objects.filter(user_to=obj, user_from=user).delete()
else:
Contact.objects.create(user_to=obj, user_from=user)
In Django 2.2 you can use add, remove and set methods (Docs)
You can also use add(), create(), or set() to create relationships, as long as your specify through_defaults for any required fields

ValueError: Lookup failed for model referenced by field

I have made Custom User model in my Django project. Here it is:
class CustomUser(User):
avatar = models.ImageField(upload_to='avatars')
about_myself = models.TextField(max_length=300)
USERNAME_FIELD = 'username'
def __str__(self):
return self.username
def is_author(self):
return 'blog.change_post' and 'blog.add_post' in self.get_all_permissions()
And after it, I changed all Foreign Keys of user to new CustomUser model. It works OK. But I make one new migration and django cause error, when I want to migrate it:
ValueError: Lookup failed for model referenced by field blog.Comment.author: main.CustomUser
My blog.Comment model:
class Comment(models.Model):
content = models.TextField()
author = models.ForeignKey(CustomUser)
date_create = models.DateTimeField(auto_now_add=True)
post = models.ForeignKey(Post)
What should I do?
Thanks!
Judging from the code you posted, you might be might be better served by extending the user model rather than replacing it. This pattern is usually called a profile model and works via a one-to-one relationship with User.
Profiles provides application specific fields and behaviors, while allowing User to go about it's usual business unchanged. It doesn't require you to muck around with rewriting auth or even necessarily change your foreign keys.
Here's an example of your code written as a profile:
class Profile(models.Model):
# Link to user :
user = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
avatar = models.ImageField(upload_to='avatars')
about_myself = models.TextField(max_length=300)
def __str__(self):
return self.user.username
def is_author(self):
return 'blog.change_post' and 'blog.add_post' in self.user.get_all_permissions()
Comment model:
class Comment(models.Model):
content = models.TextField()
author = models.ForeignKey(settings.AUTH_USER_MODEL)
date_create = models.DateTimeField(auto_now_add=True)
post = models.ForeignKey(Post)
# How to access the profile:
def check_author(self):
self.author.profile.is_author()
You'll also want to add a signal to create a new profile when a user is registered:
#receiver(post_save, sender=settings.AUTH_USER_MODEL)
def create_profile_for_new_user(sender, created, instance, **kwargs):
if created:
profile = Profile(user=instance)
profile.save()
Django docs on extending users.
If a profile approach doesn't work for you, try inheriting from AbstractUser or AbstractBaseUser instead of User. The abstract models provide the same basic functionality as User and are the preferred technique for recent Django versions.
There are a handful of additional steps however, check out the docs on creating custom users for a run down.

django forms logged in user problem

I am writing an application to help employees track projects the are working on.
Part of the form should allow logged in employees to click a drop down and see all projects they are working on. This is the part I am struggling with; specifically getting ONLY the logged in user's projects populated in a drop down. Any help or insight is much appreciated. Thanks……
models.py
class Photo(models.Model):
image = models.ImageField(upload_to='uploads/images/photo')
title = models.CharField(max_length=50)
def __unicode__(self):
return self.title
class Employee(models.Model):
user = models.ForeignKey(User, unique=True)
photo = models.ImageField(upload_to='uploads/images')
department = models.ForeignKey(Department, null=True)
phone = PhoneNumberField("Phone")
def __unicode__(self):
return self.user.get_full_name()
class Projects(models.Model):
name = models.CharField(max_length=40)
student = models.ForeignKey(Student)
photos = models.ManyToManyField(Photo, blank=True, null=True)
forms.py
class ProjectsForm(forms.ModelForm):
employee = get_object_or_404(Employee, user=user)
employee_projects = employee.projects_set.all()
name = forms.ModelChoiceField(queryset=employee_projects,
empty_label="(Select a Project)", required=True)
class Meta:
model = Projects
You need to put first two lines from ProjectsForm class definition to its initialization method and change them a bit.
class ProjectsForm(forms.ModelForm):
name = forms.ModelChoiceField(queryset=Employee.objects.all(),
empty_label="(Select a Project)", required=True)
class Meta:
model = Projects
def __init__(self, user, *args, **kwargs):
super(self, ProjectsForm).init(*args, **kwargs)
employee = get_object_or_404(Employee, user=user)
self.fields['name'].queryset = employee.projects_set.all()
Now, some explanation. Hope someone will find it useful.
In your original ProjectsForm definition, you're trying to get employee's projects when your class is defined. But this happens once your forms.py file is compiled, which takes place rarely (when you change code, for example). Also, you of course have no data that is necessary to filter projects, i.e., no user object, at that stage.
Instead, you need to do this each time the class is initialized. Initialization in Python takes place in special __init__() method. For example, when you're doing something like
form = ProjectsForm(data=request.POST)
in your view, what happens is that ProjectsForm.__init__(data=request.POST) is called to initialize ProjectsForm into an instance.
So, in our new definition, we're requiring a new argument (user) to be passed to the form when it's instantiated. So you can do something like this in your view:
form = ProjectsForm(request.user, data=request.POST)
In new initialization method, first we're calling the initialization method of parent class (which does some internal django things and should be called anyway), then use argument user to get related employee, and then assign a queryset with that employee's projects to the name field.
Sorry if I'm being too verbose.
See also:
Django, passing information when modifying queryset for ModelForm
django - dynamic select fields in forms
Why not have a many to many field in the Employee model that points to all the projects the employee can work on?
https://docs.djangoproject.com/en/dev/ref/models/fields/#django.db.models.ManyToManyField
I think that would be the best way to do it.

Categories