How to notify all users? - python

I prepared a notification app.
I would like to send a notification to all users.
If I use this line:
user = models.ForeignKey(User)
it creates me a possibility to send a notification to the user which I need to choose. I would like to have an option to send a notification to all of users in the same time
models.py
from django.db import models
from django.contrib.auth.models import User
class Notifications(models.Model):
title = models.CharField(max_length=150, verbose_name="Tytul")
content = models.TextField(verbose_name="Wiadomosci")
viewed = models.BooleanField(default=False, verbose_name="Otwarta")
user = models.ForeignKey(User)
def __unicode__(self):
return self.title
views.py
from django.shortcuts import render_to_response
from django.http import HttpResponseRedirect
from models import Notifications
def show_notification(request, notification_id):
n = Notifications.objects.get(id=notification_id)
return render_to_response('notifications.html',{'notification':n})
def delete_notification(request, notification_id):
n = Notifications.objects.get(id=notification_id)
n.viewed = True
n.save()
return HttpResponseRedirect('/accounts/loggedin')

To add a Notification for each User, here's a solution:
class Notifications(models.Model):
[...]
#classmethod
def notify_all(klass, title, content):
new_notices = list()
for u in User.objects.all():
new_notices.append(klass(user=u, title=title, content=content))
klass.objects.bulk_create(new_notices)
Then, to run this you do:
Notification.notify_all('Test title', 'Test message')

Just iterate over all users and create notification for each of them:
from django.db import transaction
with transaction.atomic():
for user in User.objects.all():
Notifications.objects.create(title="some title", content="some content",
user=user)
As side note: you have a security problem in show_notification() and delete_notification(). You show/delete notification to/by any visitor. Add filter by user like this:
#login_required
def show_notification(request, notification_id):
n = Notifications.objects.get(id=notification_id, user=request.user)
...

Related

Django Friend Request system

I am trying to make a friend request system with Django for a cat app, and I am having a problem. I have models to track the friends and the friend request. In the views I have a redirect view with a try except clause that creates a new instance of the friend request model. Then the friend request will be shown to whoever it was sent to, and they will accept or decline it. The problem I have is i don't know how to grab the info about the user to whom the friend request is sent. Any help would be appreciated. Here is the link to my project repository https://github.com/codewiz9/chatter
modles.py
from django.db import models
from django.utils.text import slugify
from django.contrib.auth import get_user_model
User = get_user_model()
# Create your models here.
class Chat(models.Model):
messages = models.TextField(blank=True, max_length=2000, null=False),
date = models.DateTimeField(blank=False, editable=False),
slug = models.SlugField(allow_unicode=True, unique=True,),
friends = models.ManyToManyField(User, through='Friend_List'),
class Friend_List(models.Model):
friend_name = models.ForeignKey(User, related_name='name', on_delete=models.CASCADE),
is_friend = models.BooleanField(default=False),
def __str__(self):
return self.user.username
class Friend_Info(models.Model):
friend_name = models.ForeignKey(User, related_name='name', on_delete=models.CASCADE),
slug = models.SlugField(allow_unicode=True, unique=True,),
class Friend_Request(models.Model):
yes_or_no = models.BooleanField(default=False),
friends = models.ManyToManyField(User, through='Friend_List'),
slug = models.SlugField(allow_unicode=True, unique=True,),
Views.py
from django.shortcuts import render
from django.urls import reverse
from django.views import generic
from .models import Chat, Friend_List, Friend_Info, Friend_Request
# Create your views here.
###Genral###
class Dashbord(generic.TemplateView):
#This classs will have the list of all the users chats
models = Chat, Friend_List
template_name = 'chat_app/dashbord.html'
###Friends###
class Friend_Dashbord(generic.ListView):
#This view will allow users to see thire friends and see thire friend requests and this will contain the button to add new friends
models = Friend_Info, Friend_List
template_name = 'chat_app/friend_dashbord.html'
class Friend_Request(generic.RedirectView):
#This is the form for sending requests S=sent
models = Friend_Request, Friend_list, Friend_Info
def get(self, request, *args, **kwargs):
friend = get_object_or_404(Friend_Info, slug=self.kwargs.get("slug"))
try:
Friend_Request.objects.create(friends=)
class Find_Friends(generic.FormView):
#this will be the page where you can serch for friends
models = Friend
template_name = 'chat_app/dashbord.html'
###Chat###
#the chat portion of the app will be handeled in two parts one will the the form to send the chat and one will be the
#list of all the chats the form view will be inclued on the Chat_list template
class Chat_List(generic.ListView):
#This will be the list of all the chats sent and resived
models = Chat
template_name = 'chat_app/dashbord.html'
class Chat_Form(generic.FormView):
models = Chat
template_name = 'chat_app/dashbord.html'
This is how I would implement such a model:
class FriendRequest(models.Model):
# create a tuple to manage different options for your request status
STATUS_CHOICES = (
(1, 'Pending'),
(2, 'Accepted'),
(3, 'Rejected'),
)
# store this as an integer, Django handles the verbose choice options
status = models.IntegerField(choices=STATUS_CHOICES, default=1)
# store the user that has sent the request
sent_from = models.ForeignKey(User, ..., related_name="requests_sent")
# store the user that has received the request
sent_to = models.ForeignKey(User, ..., related_name="requests_received")
sent_on = models.DateTimeField(... # when it was sent, etc.
Now, you will notice that the two user ForeignKey fields have related_name attributes, these are reverse accessors and are how you can get related model objects.
Say you have a given user object, you can get all of the friend requests they have sent and received using these queries:
# Friend requests sent
user.requests_sent.all()
# Friend requests received from other users
user.requests_received.all()
Those provide you with querysets of other users that you can then iterate over and access as needed.

How to put the username of the logged-in user in the databse each time a form is submitted

I have an application where a user can submit a form which goes into the database (POSTGRES).
I want to be able to automatically send the username of the user logged in to the same database, so i can keep track of who is submitting. (I do not want to put a form line with the username, i want this to be dealt with in the back-end).
what I managed to do is get the user-id, but it stays null, and I do not know how to get the username in the database and to complete it at each submission.
I hope I am clear,
thanls guys.
Here is my code
models.py
from django.db import models as db_models
from django.contrib.auth.models import User
from django.contrib.gis.db import models
class Fertidb(models.Model):
user = db_models.ManytoManyField(User, on_delete=models.CASCADE)
area = models.IntegerField()
plot = models.FileField(upload_to='KML_FILES', blank=True)
def __str__(self):
return f' Parcelles de {self.user.username}'
forms.py
from django import forms
from django.contrib.auth.models import User
from .models import Fertidb
class FertidbForm(forms.ModelForm):
class Meta:
model = Fertidb
labels = {
"plot": "Importez votre fichier KML"
}
fields = ['culture', 'area', 'plot']
views.py
from django.shortcuts import render, redirect
from django.contrib import messages
from django.contrib.auth.decorators import login_required
from .forms import FertidbForm
from django.contrib.auth.models import User
title = 'FERTISAT'
#login_required
def fertisatmap(request):
mapbox_access_token = 'pk.eyJ1IjoiaGFtemFiIiwiYSI6ImNrMHdwYmQ2bzA2OGYzbHB1Z292eGxneDgifQ.rGPQjaoWuOdnq_UdxAfQ_w'
if request.method == "POST":
o_form = FertidbForm(request.POST, request.FILES)
if o_form.is_valid():
o_form.save(commit=False)
o_form.user = request.user.username()
messages.success(request, f'Vos informations ont été envoyées')
return redirect('fertisat-map')
else:
o_form = FertidbForm()
context = {'title': title, 'o_form': o_form}
return render(request, 'fertisat/fertisatmap.html ', context, {'mapbox_access_token': mapbox_access_token})
Try to update your view like so:
from django.shortcuts import render, redirect
from django.contrib import messages
from django.contrib.auth.decorators import login_required
from .forms import FertidbForm
from django.contrib.auth.models import User
title = 'FERTISAT'
#login_required
def fertisatmap(request):
mapbox_access_token = 'pk.eyJ1IjoiaGFtemFiIiwiYSI6ImNrMHdwYmQ2bzA2OGYzbHB1Z292eGxneDgifQ.rGPQjaoWuOdnq_UdxAfQ_w'
if request.method == "POST":
o_form = FertidbForm(request.POST, request.FILES)
if o_form.is_valid():
fertidb = o_form.save(commit=False)
fertidb.user = request.user
fertidb.save()
messages.success(request, f'Vos informations ont été envoyées')
return redirect('fertisat-map')
else:
o_form = FertidbForm()
context = {'title': title, 'o_form': o_form}
return render(request, 'fertisat/fertisatmap.html ', context, {'mapbox_access_token': mapbox_access_token})
(commit=False) use for creating the model instance without submit to database, then assign current user to your new model instance fertidb.user = request.user and then call .save() to commit your data to database
Btw, mapbox_access_token suppose to stay inside settings.py in case you want to load it from environment variable when deploy production. like so:
settings.py
MAPBOX_ACCESS_TOKEN="pk.eyJ1IjoiaGFtemFiIiwiYSI6ImNrMHdwYmQ2bzA2OGYzbHB1Z292eGxneDgifQ.rGPQjaoWuOdnq_UdxAfQ_w"
views.py
from django.conf import settings
...
def fertisatmap(request):
mapbox_access_token = settings.MAPBOX_ACCESS_TOKEN
Hope that helps!
There are two issues here:
1. In your Model, you want a User, but in your form, you are assigning it the username, which I think is a string.
user = db_models.ManytoManyField(User, on_delete=models.CASCADE)
and
o_form.user = request.user.username()
Just change the second line to o_form.user = request.user.
2. You are not saving the user anyway.
You have to save your model again after you assign the user.
Thanks fo the help guys.
#Toan Quoc Ho thank you I made the modifications but I still have a problem.
The database displays the user_id, but I would like it to display the username.
I guess my problem is in the model file. How do I modify the following, so I get the username in the database.
user=deb_models.ForeignKey(User,on_delete)models.CASCADE) puts the user_id -> I would like to have the username. How do I call it ?
models.py
*from django.db import models as db_models
from django.contrib.auth.models import User
from django.contrib.gis.db import models
class Fertidb(models.Model):
user = db_models.ForeignKey(User, on_delete=models.CASCADE)
culture = models.CharField(max_length=50)
area = models.IntegerField()
plot = models.FileField(upload_to='KML_FILES', blank=True)
def __str__(self):
return f' Parcelles de {self.user.username}'*

Django Login/Signup With own users Model

I am using phpMyAdmin for the database.
I am creating own user table and store user information in it without extending the Django User Model. Now, I have a problem in the login part. I can't get data from users table with objects and authenticate function is also not working.
Here is my code:
View.py
from django.shortcuts import render,redirect
from django.http import HttpResponse
from .form import SignUp,UserLogin
from .models import users
from django.contrib.auth import authenticate,get_user_model,login,logout
from django.contrib.auth.models import User
def Userlogin(request):
form=UserLogin()
if request.method == 'POST':
user_login = UserLogin(request.POST or None)
if user_login.is_valid():
username = request.POST.get('email', '')
password = request.POST.get('password', '')
getInfo=users.objects.get(email='example#mail.com')
user=authenticate(email=username,password=password)
if user is not None and user.is_active:
login(request,user)
return redirect('/')
args={'form':form}
return render(request,'html/login.html',args)
form.py
from django import forms
from .models import users
class UserLogin(forms.Form):
email = forms.CharField(widget=forms.EmailInput(attrs=
{ 'value':'',
'class':'form-control'}))
password = forms.CharField(widget=forms.TextInput(attrs=
{ 'type': '',
'value':"mukul",
'class':'form-control'}))
model.py
from django.db import models
class users(models.Model):
id=models.AutoField(primary_key=True)
name=models.CharField(max_length=100, blank=False)
email=models.EmailField(max_length=100, blank=False, unique=True)
password=models.CharField(max_length=500, blank=False)
created_at=models.DateField(auto_now_add=True)
updated_at=models.DateField(auto_now_add=True)
def __str__(self):
return self.email
What I need:-
Run authenticate(). its not working, I don't know want is wrong. Should, i want to create new authenticate() in forms.py.
if I call users.objects.get(email='example#mail.com'), it's also not working in view.py but if run in python shell it works very well.
getInfo = users.objects.get(email='example#mail.com')
show error:
class users do not have objects member
I have Some Question
if I create own users model
Do I want to create own authenticate function for login?
Do I want to create objects.get(), objects.all(),
objects.create_user() etc?
Help me, I am working on a project and I am stuck on this errors.Thank you
Answer to your Questions First:
if I create own users model:
Do I want to create own authenticate function for login? Yes
Do I want to create objects.get(), objects.all(), objects.create_user() etc? Nope
You Need to Fix Errors:
views.py
from django.shortcuts import render,redirect
from django.http import HttpResponse
from .forms import SignUp,UserLogin #Wrong Import
from .models import users
from django.contrib.auth import authenticate,get_user_model,login,logout
from django.contrib.auth.models import User
def Userlogin(request):
form=UserLogin()
if request.method == 'POST':
user_login = UserLogin(request.POST or None) #Indentation
if user_login.is_valid():
username = request.POST.get('email', '')
password = request.POST.get('password', '')
getInfo=users.objects.get(email='example#mail.com')
user=authenticate(email=username,password=password)
if user is not None and user.is_active:
login(request,user)
return redirect('/')
args={'form':form} #Fix Indentation
return render(request,'html/login.html',args) #Fix Indentation
Models.py
class users(models.Model):
id=models.AutoField(primary_key=True)
name=models.CharField(max_length=100, blank=False)
email=models.EmailField(max_length=100, blank=False, unique=True)
password=models.CharField(max_length=500, blank=False)
created_at=models.DateField(auto_now_add=True)
updated_at=models.DateField(auto_now_add=True)
def __str__(self):
return self.email
Also What you need to do is Run Migrations.
python manage.py makemigrations appname
python manage.py migrate
This would Create the Model in the Database Automatically and thus ORM of Django would work for .objects.get
=========== Update =========
Change Models.py (Extend the Default Users as It already Contains Email and Password Fields)
from django.db import models
from django.contrib.auth.models import User as AuthUser, UserManager
# Extend the base User model
class User(AuthUser):
class Meta:
db_table = 'user'
active = models.CharField(max_length=1)
last_modified = models.DateTimeField("last modified")
objects = UserManager()
Override the Django Model Backend for User
class CustomAuth(ModelBackend):
def authenticate(**credentials):
return super(CustomAuth, self).authenticate(**credentials)
def authenticate(self, username=None, password=None):
# Check the username/password and return a User.
if username != None and password != None:
# Get the user
try:
user = User.objects.get(email=username)
if user.check_password(password):
logger.info('User is authenticated, logging user in')
return user
except User.DoesNotExist:
pass
return None
def get_user(self, user_id):
try:
return User.objects.get(id=user_id)
except User.DoesNotExist:
return None
now you can use it as:
user = authenticate(username='test#gmail.com', password='testUser')
for Further Reference: https://www.micahcarrick.com/django-email-authentication.html

django-registration seems to be shortening hashed password when using subclassed RegistrationView

I'm trying to setup django-registration form with an extra field or two. I've read the documentation and scoured StackOverflow. I'm getting a problem where the user is registered with the new fields but when I try and login it doesn't recognise the password.
I've created a new view (I've just cut and pasted register from django-registration because I just want it running initially):
class MyRegistrationView (RegistrationView):
form_class = UserRegForm
def register(self, form):
new_user = RegistrationProfile.objects.create_inactive_user(
form,
site=get_current_site(self.request)
)
signals.user_registered.send(sender=self.__class__,
user=new_user,
request=self.request)
return new_user
It uses this form:
class UserRegForm(RegistrationForm):
CHOICES = Institution.objects.all().order_by('name')
institution=forms.ChoiceField(choices=( (x.id, x.name) for x in CHOICES ),
required = True)
These are the additional models:
class Institution(models.Model):
name = models.CharField(max_length=200)
def __unicode__(self):
return u'%s' % (self.name)
class UserProfile(models.Model):
user=models.OneToOneField(User, on_delete=models.CASCADE)
institution=models.ForeignKey(
Institution,
null=True,
blank=True)
def __unicode__(self):
return u'%s' % (self.user)
My URL
url(r'^register', views.MyRegistrationView.as_view(form_class=UserRegForm), name='registration_register'),
And I've added this to save the data: from models import UserProfile from forms import UserRegForm
def user_created(sender, user, request, **kwargs):
form = UserRegForm(request.POST)
try: data = UserProfile.objects.get(user=user)
except: data = UserProfile(user=user)
data.institution = form.data["institution"]
data.save()
from registration.signals import user_registered
user_registered.connect(user_created)
Everything works in that the user is registered, an email is sent out, the institution is saved to the UserProfile, but when I try and login using the new user (having activated the account) it tells me the username and password don't match.
When I look at the database the hashed paasword string seems to be 10 characters shorter than the admins (setup using manage.py createsuperuser) so I am doing something I shouldn't or not doing something I should.
Help would be much appreciated.
I solved this by basically copying all of RegistrationView into MyRegistrationView. The login now works are well. I'm not sure why this was necessary.
from registration.backends.model_activation.views import RegistrationView
from registration.models import RegistrationProfile
from registration import signals
from django.contrib.sites.shortcuts import get_current_site
from django.core import signing
from django.template.loader import render_to_string
from django.conf import settings
REGISTRATION_SALT = getattr(settings, 'REGISTRATION_SALT', 'registration')
class MyRegistrationView (RegistrationView):
form_class = UserRegForm
email_body_template = 'registration/activation_email.txt'
email_subject_template = 'registration/activation_email_subject.txt'
def register(self, form):
new_user = self.create_inactive_user(form)
signals.user_registered.send(sender=self.__class__,
user=new_user,
request=self.request)
return new_user
def get_success_url(self, user):
return ('registration_complete', (), {})
def create_inactive_user(self, form):
"""
Create the inactive user account and send an email containing
activation instructions.
"""
new_user = form.save(commit=False)
new_user.is_active = False
new_user.save()
self.send_activation_email(new_user)
return new_user
def get_activation_key(self, user):
"""
Generate the activation key which will be emailed to the user.
"""
return signing.dumps(
obj=getattr(user, user.USERNAME_FIELD),
salt=REGISTRATION_SALT
)
def get_email_context(self, activation_key):
"""
Build the template context used for the activation email.
"""
return {
'activation_key': activation_key,
'expiration_days': settings.ACCOUNT_ACTIVATION_DAYS,
'site': get_current_site(self.request)
}
def send_activation_email(self, user):
"""
Send the activation email. The activation key is simply the
username, signed using TimestampSigner.
"""
activation_key = self.get_activation_key(user)
context = self.get_email_context(activation_key)
context.update({
'user': user
})
subject = render_to_string(self.email_subject_template,
context)
# Force subject to a single line to avoid header-injection
# issues.
subject = ''.join(subject.splitlines())
message = render_to_string(self.email_body_template,
context)
user.email_user(subject, message, settings.DEFAULT_FROM_EMAIL)
Remaining issue is it just reloads the Registration page rather than going to registration complete?

custome user creation in django fields not storing value

I am trying to make a user registration form in django.
I browsed through many links but I am still confused. I am making some sill mistake please point it out.
here is my code:
models.py
from django.db import models
from django.db.models.signals import post_save
from django.contrib.auth.models import User
class UserProfile(models.Model):
mobile = models.CharField(max_length = 20, null=False)
address = models.CharField(max_length = 200)
user = models.OneToOneField(User, unique=True)
def create_user_profile(sender, instance, created, **kwargs):
if created:
UserProfile.objects.create(user=instance)
post_save.connect(create_user_profile, sender=User)
forms.py
from django import forms
from django.contrib.auth.models import User
from django.contrib.auth.forms import UserCreationForm
class CustomerRegistrationForm(UserCreationForm):
mobile = forms.CharField(max_length = 20)
address = forms.CharField(max_length = 200)
class Meta:
model = User
fields = ('username','email','mobile','address','password1','password2')
view.py
from django.shortcuts import render_to_response
from django.http import HttpResponseRedirect
from django.template import RequestContext
from django.core.context_processors import csrf
from neededform.forms import CustomerRegistrationForm
def register(request):
print "I am in register function"
if request.method == 'POST':
if request.method == 'POST':
form = CustomerRegistrationForm(request.POST)
if form.is_valid():
f = form.save()
return HttpResponseRedirect('/registered/')
else:
args = {}
args.update(csrf(request))
args['form'] = CustomerRegistrationForm()
return render_to_response('User_Registration.html', args ,context_instance = RequestContext(request))
what I am thinking is that when I do a form.save() in views.py, django should create the user in auth_user table and must insert the values (i.e mobile and address ) in the UserProfile table also.
but what happening is that it is inserting data in auth_user table correctly but in the UserProfile table only id and user_id coloumns are filled, mobile and address both remains empty.
What am I doing wrong ? What else must be done ?
Thank you.
Take a look at the following:
def create_user_profile(sender, instance, created, **kwargs):
if created:
UserProfile.objects.create(user=instance)
You create a UserProfile object which only has its user attribute set!
I don't think that using signal is the best approach to your problem since it's not easy to pass the mobile and address from your form to the Profile creation point. Instead you can override the save() method of your CustomerRegistrationForm where you'd first save the user and then create the profile. Something like this:
class CustomerRegistrationForm(UserCreationForm):
# rest code ommited
def save(self, commit=True):
user = super(CustomerRegistrationForm, self).save()
p = UserProfile.objects.get_or_create(user=user )
p[0].mobile = self.cleaned_data['mobile']
p[0].address = self.cleaned_data['address']
p[0].save()
return user

Categories