I want to create a messaging function in ma django app. User should be able to write other users a textmessage.
models.py
from django.contrib.auth.models import User
class Message(models.Model):
recipient = models.ForeignKey(User, null=True)
contentDescription = models.CharField(max_length=1000, null=True)
By default, with no forms.py entry I get a selection, which will be unuseful with many users. I want the message sender to type in the user name, or in the first step the user id (which I could resolve with ajax from the name) .
Integer
But with forms.py
recipient = forms.IntegerField( widget=forms.NumberInput , required=False,)
I get:
Cannot assign "11": "Transport.recipient" must be a "User" instance.
ChoiceField and NumberInput
with:
recipient = forms.ChoiceField( widget=forms.NumberInput, required=False,)
I get the error message "not valid"
Is it possible to write the foreignkey 'manually' at all?
Try this:
recipient = forms.ModelChoiceField(queryset=User.objects.all(), widget=forms.Select, required=False)
considering your
models.py -
from django.contrib.auth.models import User
class Message(models.Model):
recipient = models.ManytoMany(User, null=True)
contentDescription = models.TextField()
forms.py
from .models import Message
from django import forms
from django.contrib.auth.models import User
class MailForm(forms.ModelForm):
recipient = forms.Charfield()
class Meta:
model = Message
fields = ('contentDescription',)
def clean_recipient(self):
user_list = self.cleaned_data.get('recipient')
# considering you post user_list of usernames as 'username1,username2,username3'
if user_list is not None:
user_list = user_list.split(',')
user_qs = User.objects.filter(username__in=userlist)
else:
raise forms.ValidationError('Error in this field')
return user_qs
def save(self, user_qs):
self.instance.user = user_qs
return super().save()
in views.py -
from .forms import MailForm
def your_view(request):
form = MailForm(request.POST or None)
if form.is_valid():
user_qs=form.cleaned_data.get('recipient')
form.save(user_qs)
#return render here
else:
#create your context here and return render
This is not perfect but can give you an idea how to implement. With the details you gave this is the best I can do for now.
Related
Based on my django project I want to add multiple users to a group and I'm trying to do this using a form. But when I try adding choices via CheckBoxSelectMultiple() widget its not working as expected.
models.py file
from django.db import models
from members.models import User
from django.contrib.auth.models import Group
class Sprint(models.Model):
status_choice = [('Working','Working'), ('Closed','Closed')]
sprint_name = models.CharField(max_length=180)
sprint_created = models.DateTimeField(auto_now= True)
lead = models.ForeignKey(User, on_delete=models.CASCADE,
related_name='team_lead')
sprint_members = models.ForeignKey(Group, on_delete=models.CASCADE, related_name = "member")
sprint_period = models.PositiveIntegerField()
sprint_status = models.CharField(max_length=10, choices=status_choice, default='Working')
forms.py file
from django import forms
from .models import Sprint
from members.models import User
from django.core.exceptions import ValidationError
from django.contrib.auth.models import Group
class SprintForm(forms.Form):
sprint_name = forms.CharField()
sprint_period = forms.IntegerField(label="Sprint period (in days)", min_value=7)
lead = forms.ModelChoiceField(queryset= User.objects.filter(role = 'Developer'),
label="Team Lead")
sprint_members = forms.ModelChoiceField(queryset= User.objects.filter(role =
'Developer'), widget= forms.CheckboxSelectMultiple(), label="Team members")
# class Meta:
# model = Sprint
# fields = ['sprint_name', 'lead', 'sprint_period', 'sprint_members']
def clean(self):
cleaned_data = super().clean()
lead = cleaned_data.get('lead')
team = cleaned_data.get('sprint_members')
if team and lead:
if lead in team:
raise ValidationError('Team lead cant be in team')
def save(self):
team = Group.objects.get_or_create(name=f'team{self.cleaned_data["sprint_name"]}')[0]
for team_member in self.cleaned_data['sprint_members']:
team.user_set.add(team_member)
Sprint.objects.update_or_create(
sprint_name=self.cleaned_data["sprint_name"],
lead=self.cleaned_data["lead"],
sprint_period=self.cleaned_data["sprint_period"],
_members=team
)
views.py file
class SprintCreationView(generic.FormView):
model = Sprint
template_name = 'sprint_creation.html'
form_class = SprintForm
def form_valid(self, form):
form.save()
return super().form_valid(form)
When trying to submit the form it is showing "Select a valid choice. That choice is not one of the available choices."
class Setting(models.Model):
id=models.AutoField(primary_key=True, unique=True)
ldap_server = models.CharField(max_length=100, default='ldap://yourDomain.in')
ldap_server_username = models.CharField(max_length=100, null=True)
ldap_server_password = models.CharField(max_length=100, null=True)
def save(self, *args, **kwargs):
ldap_server=self.ldap_server
ldap_server_username = self.ldap_server_username
ldap_server_password = self.ldap_server_password
try:
l = ldap.initialize(ldap_server)
l.protocol_version = ldap.VERSION3
l.set_option(ldap.OPT_REFERRALS, 0)
l.simple_bind_s(ldap_server_username, ldap_server_password)
super(Setting, self).save(*args, **kwargs)
except:
messages.error(request, "You have logged in..!")
here I faced the error in
messages.error(request, "You have logged in..!")
I can't use
messages.error(request, "You have logged in..!")
Anybody know alternative way to show error
message.
Try this in admin.py:
#admin.py
from models import Setting
from django.contrib import admin
from django import forms
class SettingForm(forms.ModelForm):
class Meta:
model = Setting
def clean(self):
ldap_server = self.cleaned_data.get('ldap_server')
ldap_server_username = self.cleaned_data.get('ldap_server_username')
ldap_server_password = self.cleaned_data.get('ldap_server_password')
# your ldap logic here
if your_condition:
raise form.ValidationErro('You have logged in..!')
return self.cleaned_data
class SettingAdmin(admin.ModelAdmin):
form = SettingForm
list_display = ('ldap_server', 'ldap_server_username', 'ldap_server_password')
admin.site.register(Setting, SettingAdmin)
Remove save() method from your model.
You can move SettingForm in forms.py file and then import it in admin.py
I hope this will help
I've been trying creating a user profile form using built-in User of django.contrib.auth.models. Everything is working fine but after filling the fields into the form(which is displaying), I am encountering an INTEGRITY ERROR AT / saying NOT NULL CONSTRAINT failed.
You can see this image using this link to know exactly what the error is showing.
This is my models.py file
from django.db import models
from django.contrib.auth.models import User
from django.core.validators import MaxValueValidator
# Create your models here.
class UserProfileInfo(models.Model):
user = models.OneToOneField(User,on_delete=models.CASCADE, null=True)
phone_number = models.PositiveIntegerField(validators=
[MaxValueValidator(9999999999)],blank=True)
def __str__(self): #This will print out this model
return self.user.username
This is my forms.py file.
from django import forms
from django.contrib.auth.models import User
from Login_Signup_Form.models import UserProfileInfo
class UserForm(forms.ModelForm):
password = forms.CharField(widget=forms.PasswordInput())
class Meta:
model=User
fields=('first_name','last_name','username','email','password',)
class UserProfileForm(forms.ModelForm):
class Meta:
model=UserProfileInfo #this is model
fields=('phone_number',)
This is my views.py file.
from django.shortcuts import render
from Login_Signup_Form.forms import UserForm,UserProfileForm
from Login_Signup_Form.models import UserProfileInfo
# Create your views here.
def index(request):
return render(request,'base.html')
def register(request):
registered=False
if request.method == 'POST':
user_form = UserForm(data=request.POST)
user_phone_number=UserProfileForm(data=request.POST)
if user_form.is_valid() and user_phone_number.is_valid():
user=user_form.save()
user.set_password(user.password)
user.save()
phone = user_phone_number.save()
phone.user=user
else:
#Printing the errors
print(user_form.errors,user_phone_number.errors)
else:
user_form = UserForm()
user_phone_number = UserProfileForm()
return render(request, 'base.html',{'user_form':user_form, '
phone_number':user_phone_number})
The error probably comes from an empty phone number in your form. You allow an empty phone_number in your form with blank=True but you don't allow it on the database level, you need to add null=True as well:
phone_number = models.PositiveIntegerField(validators=
[MaxValueValidator(9999999999)], blank=True, null=True)
See this great answer.
With blank=True the field is not required and the form will validate but it will raise the integrity error because null=True is not here. That wouldn't happen with a CharField though, the blank value would be stored as empty string. This only happens because of the PositiveIntegerField.
All other data is saved ideally but as shown below, the user id part shows as a pull down bar and a null value which should be a signed-in username.
What's wrong with my code?
The database page
Here's my code.
views.py
from .models import Markers
from .forms import AddMarkersInfo
from django.http import HttpResponse
def addinfo(request):
if request.method == 'POST':
mks = AddMarkersInfo(request.POST)
if mks.is_valid():
submit = mks.save(commit=False)
submit.user = request.user
submit.save()
name = mks.cleaned_data['name']
address = mks.cleaned_data['address']
description = mks.cleaned_data['description']
type = mks.cleaned_data['type']
lat = mks.cleaned_data['lat']
lng = mks.cleaned_data['lng']
Markers.objects.get_or_create(name=name, address=address, description=description, type=type, lat=lat, lng=lng)
return render(request, 'home.html', {'mks': mks })
else:
mks = AddMarkersInfo()
return render(request, 'home.html', {'mks': mks})
models.py
from django.db import models
from django.contrib.auth.models import User
from django.conf import settings
from django.contrib.auth import get_user_model
def get_sentinel_user():
return get_user_model().objects.get_or_create(username='deleted')[0]
class Markers(models.Model):
User = settings.AUTH_USER_MODEL
use_id= models.ForeignKey(User, null=True, on_delete=models.SET(get_sentinel_user),)
name = models.CharField(max_length=60,default = 'name')
address = models.CharField(max_length=100,default = 'address')
description = models.CharField(max_length=150, default='description')
types = (
('m', 'museum'),
('s', 'school'),
('r', 'restaurant'),
('o', 'other'),
)
type = models.CharField(max_length=60, choices=types, default='museum')
lat = models.IntegerField()
lng = models.IntegerField()
forms.py
from django import forms
from maps.models import Markers
class AddMarkersInfo(forms.ModelForm):
class Meta:
model = Markers
fields = ['name','address','description', 'type','lat','lng',]
Well, first of all, you should remove the lines from django.contrib.auth.models import User and User = settings.AUTH_USER_MODEL in models.py if you are going to use settings.AUTH_USER_MODEL. You should use only one of the two.
And you can change your field to:
use_id= models.ForeignKey(settings.AUTH_USER_MODEL, ...
Secondly, it seems like you are duplicating the creation. The lines
submit = mks.save(commit=False)
submit.user = request.user
submit.save()
already create an Markers instance, so there is no need to call Markers.objects.get_or_create(... after that.
And, according to you models, the field should be submit.use_id instead of submit.user.
Now, if I understand your question correctly you want to make the use_id field read-only in your form/template.
I don't know why that field is even showing up in your form, since it is not listed in your forms Meta.fields.
You could try something like setting the widget attribute readonly:
class AddMarkersInfo(forms.ModelForm):
class Meta:
model = Markers
fields = ['use_id', 'name', 'address', 'description', 'type', 'lat', 'lng']
widgets = {
'use_id': forms.Textarea(attrs={'readonly': 'readonly'}),
}
I have 2 class from my model
class APPLICANT_DATA(models.Model):
FIRST_NAME= models.CharField(max_length=20)
LAST_NAME= models.CharField(max_length=20)
MIDDLE_NAME= models.CharField(max_length=20)
and
class Applicant_status(models.Model):
fkey = models.ForeignKey(APPLICANT_DATA)
COMMENTS = models.CharField(max_length=100, null=True)
date_of_app = models.DateTimeField(auto_now_add=True, blank=True)
how do i make my 'Applicant_status' to populate whenever a data in 'APPLICANT_DATA' is inserted?
Here is my views.py
def save_page(request):
form = application_form(request.POST)
if request.method == 'POST':
if form.is_valid():
emails = form.cleaned_data['EMAIL']
mail = EmailMessage("Your activation and application code is: asdasd, do not show this to anyone", to=[emails])
mail.send()
cde = form.save(commit=False)
applicant_status.objects.create(fk=cde.id)
cde.save()
return HttpResponseRedirect('verify')
else:
form = application_form()
return render(request, 'frontend/apply.html', {'form': form})`
EDIT: My forms.py
from django.forms import ModelForm
from django import forms
from .models import APPLICANT_DATA
from django.core.exceptions import ValidationError
from django.core.validators import RegexValidator
class application_form(ModelForm):
FIRST_NAME = forms.CharField( max_length=20, label = ("First Name"),
. . .
class Meta:
model = APPLICANT_DATA
fields = ('FIRST_NAME', 'LAST_NAME', 'MIDDLE_NAME', )
error is (1048, "Column 'fkey' cannot be null")
Sorry if this was a newbie question
Use django signals to achieve this. https://docs.djangoproject.com/en/1.8/topics/signals/
Or you can manually save Applicant_Status with fk set to Application_Data you have just received in your view.