Django signals not receiving/working - python

i am using django default receiver to handle signal. but its not working.
i have modified User model in APP1 whenver new User object create a receiver in APP2 signal.py is listen to it, but its not working.
app1/model.py
class User(BaseModel, AbstractBaseUser, PermissionsMixin):
email = models.EmailField(
verbose_name='email address',
max_length=255,
unique=True,
)
username = models.CharField(max_length=40, unique=True)
first_name = models.CharField(max_length=30, blank=True, null=True)
last_name = models.CharField(max_length=30, blank=True, null=True)
is_active = models.BooleanField(default=True)
is_admin = models.BooleanField(default=False)
is_staff = models.BooleanField(default=False)
is_email_verified = models.BooleanField(default=False)
is_paid = models.IntegerField(default=0)
access_token = models.CharField(max_length=128, blank=True)
objects = UserManager()
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['username']
class Meta:
db_table = 'users'
def __str__(self):
return self.email
app2/signals.py
from django.conf import settings
from django.db.models.signals import post_save
from django.dispatch import receiver
from accounts.models import User
#receiver(post_save, sender=User)#settings.AUTH_USER_MODEL)
def create_auth_token(sender, instance=None, created=False, **kwargs):
print ("token generated")
if created:
print("data at signal ****", instance.email, instance)

Finally I got the answer. Its because I'm not importing signals.py on startup.
Working code
apps.py
from __future__ import unicode_literals
from django.apps import AppConfig
class StreamsConfig(AppConfig):
name = 'streams'
def ready(self):
print("at ready")
import streams.signals
init.py
default_app_config = 'streams.apps.StreamsConfig'
after this change I'm receiving signals
Update:
As per django 3.0 documentation for newer applications adding default_app_config in init.py is not required if you are using dotted path to application configuration.
https://docs.djangoproject.com/en/3.0/ref/applications/#django.apps.AppConfig.ready
Just replace
INSTALLED_APPS = (
...,
'streams',
)
with
INSTALLED_APPS = (
...,
'streams.apps.StreamsConfig',
)
It will work.

Related

'project.Account' has no ForeignKey to 'project.Object': How to link an account model to the objects of a project?

I am trying to create an announcement website (All) that can be visible to others (the Users, for which I added an Account). For this I wanted to modify a little the user profile to add fields like telephone, email address...
So I modified admin.py:
from django.contrib import admin
from .models import Todo, Account
from django.contrib.auth.models import User
class AccountInline(admin.StackedInline):
model = Account
can_delete = False
verbose_name_plural = 'Accounts'
class TodoAdmin(admin.ModelAdmin):
readonly_fields = ('created',)
inlines = (AccountInline, )
admin.site.unregister(User)
admin.site.register(Todo, TodoAdmin)
But got back:
<class 'todo.admin.AccountInline'>: (admin.E202) 'todo.Account' has no ForeignKey to 'todo.Todo'.
So I added a ForeignKey to Todo with account = models.ForeignKey(Account, on_delete=models.CASCADE):
from django.db import models
from django.contrib.auth.models import User
class Account(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
email = models.CharField(max_length=100)
firstname = models.CharField(max_length=30)
lastname = models.CharField(max_length=50)
company = models.CharField(max_length=5)
def __str__(self):
return self.user.username
class Todo(models.Model):
title = models.CharField(max_length=100)
datetime = models.DateTimeField()
memo = models.TextField(blank=True)
created = models.DateTimeField(auto_now_add=True)
datecompleted = models.DateTimeField(null=True, blank=True)
important = models.BooleanField(default=False)
user = models.ForeignKey(User, on_delete=models.CASCADE)
account = models.ForeignKey(Account, on_delete=models.CASCADE)
def __str__(self):
return self.title
But I still have the error, and I don't have any Users in the admin panel anymore
You accidentally wrote unregister for Users in your admin.py file. It should be admin.site.register(User)
You misinterpretted the error: the error states that you don't have a foreign key in your Account model to Todo.
This means your inline admin code isn't correct as it's expecting the other way around.

How can I hide current uploaded image location path in django?

I have made a feature in Django where every user can change his platform's logo. The image selected by the user will be saved in static/{user.customer.public_id}/platformLogo/image.jpg. When i save the changes, i can see the uploaded image's path which also contain unique public ID which i don't want user to see for security purpose. Can anyone help me to hide this image path in Django for user? Attaching my code part here below.
Here we can see the image path which has unique ID in path, which we need to hide
Here is the uploaded image path directory
Here is my models.py
from sre_constants import CATEGORY
from unicodedata import category
from attr import fields
from django.db import models
from datetime import date
from django.contrib.auth.models import User
import uuid
def upload_path(instance, filename):
filename = str(date.today())
name = instance.user.customer.public_id.hex
return f'{name}/platformLogo/{filename}.jpg'
class Customer(models.Model):
user = models.OneToOneField(User, null=True, blank =True, on_delete=models.CASCADE)
public_id = models.UUIDField(primary_key=True, default = uuid.uuid4, editable=False)
date_created = models.DateTimeField(auto_now_add=True, null=True)
name = models.CharField(max_length=200, null=True)
otp_code = models.CharField(max_length=6, null=True)
first_name = models.CharField(max_length=200, null=True)
last_name = models.CharField(max_length=200, null=True)
email = models.CharField(max_length=200, unique=True)
phone = models.CharField(max_length=200, null=True)
profile_pic= models.ImageField(upload_to=upload_path, default='logo.png', null=True, blank=False,)
def __str__(self):
return self.name
Here is my views.py
#login_required(login_url='login')
def accountSetting(request):
customer = request.user.customer
form = CustomerForm(instance= customer)
if request.method == 'POST':
form = CustomerForm(data=request.POST, files=request.FILES, instance=customer)
if form.is_valid():
form.save()
context = {'form': form}
if request.user.is_anonymous:
return redirect("/")
return render(request, 'account-settings.html', context)
Here is my forms.py
from django.forms import ModelForm
from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth.models import User
from .models import Customer
from django import forms
class CustomerForm(ModelForm):
class Meta:
model = Customer
fields = '__all__'
exclude = ['user', 'email','name','otp_code']
class CreateUserForm(UserCreationForm):
class Meta:
model = User
fields = ['username','first_name','last_name', 'email', 'password1', 'password2']
Here is settings.py
STATIC_URL = '/static/'
STATICFILES_DIRS = [os.path.join(BASE_DIR, 'static')]
MEDIA_URL = '/platformLogo/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'static/platformLogo')
Since you already made public_id UUID, why not hash the logo and image name?
In Django environments I’ve used xsendfile with Apache or nginx. You end up placing the images in a folder that is accessible by Apache and served by apache, but can only be served after a request to the Django backend. It prevents all of the logos being visible to prying eyes.

Accessing UserProfile data from foreign key related Post

I am currently working on a little django app, the app is like a social media app.
User can post, like and comment.
I recently created the User Profiles. Which I can now see the user for that user profile in my view, but I cant seem to dig into the Posts that may be related to the UserProfile.
what I am trying to do is in my view of HTML, I want to be able to get the post from the userprofile and the comment, and likes.
But I have tried everything and nothing works.
Currently in my HTML view I have rendered {{ profile.user }} and it displays the users name, but If I try profile.user.post or profile.user.comments I get nothing.
Here is some code to show where I am at.
Any help would be much appreciated.
Profile View.
def profile(request):
profile = get_object_or_404(UserProfile, user=request.user)
template = 'profiles/profile.html'
context = {
'profile': profile,
# 'posts': posts
}
return render(request, template, context)
Profile Model
from django.db import models
from django.contrib.auth.models import User
from django.db.models.signals import post_save
from django.dispatch import receiver
class UserProfile(models.Model):
"""
A user profile model to link posts and likes
"""
user = models.OneToOneField(User, on_delete=models.CASCADE, related_name="profile")
def __str__(self):
return self.user.username
Post Model
from django.db import models
from django.contrib.auth.models import User
from cloudinary.models import CloudinaryField
from profiles.models import UserProfile
class Post(models.Model):
user_profile = models.ForeignKey(UserProfile, on_delete=models.CASCADE, null=True, blank=True, related_name='user_posts')
title = models.CharField(max_length=220, unique=True)
location = models.CharField(max_length=220)
rating = models.DecimalField(
max_digits=6, decimal_places=2)
#slug = models.SlugField(max_length=220, unique=True)
author = models.ForeignKey(User, on_delete=models.CASCADE, related_name="activity_post")
updated_on = models.DateTimeField(auto_now=True)
description = models.TextField()
featured_image = CloudinaryField('image', blank=False)
created_on = models.DateTimeField(auto_now_add=True)
likes = models.ManyToManyField(User, related_name='activity_likes', blank=True)
like_count = models.BigIntegerField(default='0')
class Meta:
ordering = ['-created_on']
def __str__(self):
return self.title
def number_of_likes(self):
return self.likes.count()
def liked_by_user(self):
return self.likes.values_list('id', flat=True)
class Comment(models.Model):
post = models.ForeignKey(Post, on_delete=models.CASCADE, related_name='comments')
name = models.CharField(max_length=80)
email = models.EmailField()
body = models.TextField()
created_on = models.DateTimeField(auto_now_add=True)
class Meta:
ordering = ['created_on']
def __str__(self):
return f"Comment {self.body} by {self.name}"
enter code here
My Signal to create / save the profile, also have it registered in apps.py
from django.contrib.auth.models import User
from django.db.models.signals import post_save
from django.dispatch import receiver
from .models import UserProfile
#receiver(post_save, sender=User)
def create_profile(sender, instance, created, **kwargs):
if created:
UserProfile.objects.create(user=instance)
#receiver(post_save, sender=User)
def save_profile(sender, instance, **kwargs):
instance.profile.save()

Django Admin show same database name when i am using inherited user class

I am creating a custom user class and then I am inheritance this user class to another two classes called Customer and Agent.
from django.db import models
from django.contrib.auth.models import AbstractUser
from django.db.models.deletion import CASCADE
class User(AbstractUser):
username = models.CharField(max_length=50, blank=False, null=False, unique=True)
email = models.EmailField(('email address'), blank=False, null=False, unique=True)
phone_no = models.CharField(max_length=10)
isAgent = models.BooleanField(default=False)
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['username', 'first_name', 'phone_no']
def __str__(self):
return self.username
class Customer(User):
pass
class Agent(User):
company_name = models.CharField(max_length=150, default="", null=False, blank=False)
company_desc = models.CharField(max_length=1000, default="")
and then i am register this model class in admin pannel like this...
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from .models import Customer, User, Agent, Destination, Trip, Payment
admin.site.register(User, UserAdmin)
#admin.register(Customer)
class CustomerAdmin(admin.ModelAdmin):
list_display = ['username', 'email']
#admin.register(Agent)
class AgentAdmin(admin.ModelAdmin):
list_display = ['username', 'email', 'company_name']
NOTE : I am also create a model classes like Destination,Trip,Payment just ignore this class...
but in my adminsite http://127.0.0.1:8000/admin/ it is how like this...
https://i.stack.imgur.com/D8sX3.png
==> user class name as "User" , Customer class name as "User" as well as Agent class name as "User"
soo why my orignal model class name is not occure..?

How to make relationship between a model and AbstractUser/AnonymousUser based on authentication?

I'm trying to make a Pastebin clone using Django.
In my models.py file, I have two models:
CustomUser which is inherited from AbstractUser
Snippet which is inherited from Model
from .helpers import url_shortner
from django.db import models
from django.contrib.auth.models import AbstractUser
class CustomUser(AbstractUser):
bio = models.TextField(max_length=500, blank=True)
location = models.CharField(max_length=30, blank=True)
birth_date = models.DateField(null=True, blank=True)
def __str__(self):
return self.username
class Snippet(models.Model):
id = models.CharField(primary_key=True, max_length=19, default=url_shortner, editable=False)
owner = models.ForeignKey(CustomUser, on_delete=models.CASCADE)
title = models.CharField(max_length=50, default="Untitled")
content = models.TextField()
creation_date = models.DateTimeField(auto_now_add=True)
expiration_date = models.DateTimeField(null=True, blank=True)
def __str__(self):
return self.title
Now if there's a guest user want to make a snippet, as far as I know the owner field for this snippet should have a relation to AnonymousUser object so, How to implement it? Is there any kind of relations can relate Snippet object to these two models (CustomUser & GuestUser)? what is the best practice for this case?
Pastebin are using unique useID for guest users so that they can identify a user (without login).
When a guest user open first time their website they store a unique userID in browser local storage. after in further request they identify guest user by this userID.
In future If the user logs in then they search all content in database by userID and link with login user...
To make it...
firstly generate unique id ..
import uuid
quest_id = uuid.uuid4()
Send this guest_id to browser when user come first time in your
website.
get quest_id from browser in each request to identify a guest user
save all activity of guest user by guest_id in database
if guest user become login user then search all data by guest_id in
database and connect it with this logined user
To identify user is guest user or login user use ..
if request.user.is_authenticated:
print('this is login user')
make owner field in your model optional
and add a extra field guest_id
from .helpers import url_shortner
from django.db import models
from django.contrib.auth.models import AbstractUser
class CustomUser(AbstractUser):
bio = models.TextField(max_length=500, blank=True)
location = models.CharField(max_length=30, blank=True)
birth_date = models.DateField(null=True, blank=True)
def __str__(self):
return self.username
class Snippet(models.Model):
id = models.CharField(primary_key=True, max_length=19, default=url_shortner, editable=False)
owner = models.ForeignKey(CustomUser, null=true, on_delete=models.CASCADE)
title = models.CharField(max_length=50, default="Untitled")
content = models.TextField()
guest_id = models.CharField(max_length=100, blank=True)
creation_date = models.DateTimeField(auto_now_add=True)
expiration_date = models.DateTimeField(null=True, blank=True)
def __str__(self):
return self.title
if user is guest user then ..
Snippet.objects.create(owner=None ,guest_id=guest_id .....)
get guest_id from browser in each request
i hope this will helpful to you !!
You can do it with :
1. Change the models to :
`
from django.contrib.auth.models import User
class CustomUser(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
bio = models.TextField(max_length=500, blank=True)
location = models.CharField(max_length=30, blank=True)
birth_date = models.DateField(null=True, blank=True)
def __str__(self):
return self.username
class Snippet(models.Model):
id = models.CharField(primary_key=True, max_length=19,
default=url_shortner, editable=False)
owner = models.ForeignKey(CustomUser, null=True,on_delete=models.CASCADE)
title = models.CharField(max_length=50, default="Untitled")
content = models.TextField()
creation_date = models.DateTimeField(auto_now_add=True)
expiration_date = models.DateTimeField(null=True, blank=True)
def __str__(self):
return self.title
`
2. To test in views.py, if the user is guest or no you can do it using:
if request.user.is_authenticated:
pass
==> This test returns false if the user is a GuestUser :)

Categories