I have a view like:
def Registration(request):
RegForm = RegistrationForm(request.POST or None)
if request.method == 'POST':
if RegForm.is_valid():
clearUserName = RegForm.cleaned_data['userNm']
clearPass = RegForm.cleaned_data['userPass']
hashedpasswithsalt = bcrypt.hashpw(clearPass, bcrypt.gensalt(14))
RegForm.save()
try:
return HttpResponseRedirect('/Newuser/?userNm=' + clearUserName)
except:
raise ValidationError(('Invalid request'), code='300') ## [ TODO ]: add a custom error page here.
else:
RegForm = RegistrationForm()
return render(request, 'VA/reuse/register.html', {
'RegForm': RegForm
})
RegistrationForm
class RegistrationForm(ModelForm):
userPass = forms.CharField(widget=forms.PasswordInput, label='Password')
class Meta:
model = Client
fields = ['userNm','userPass']
Why is it storing in plaintext?
I'm trying to take the cleaned_data[] of userPass from a modelfrom and hash it prior to sending to the db.
Try bcrypt.hashpw(clearPass.encode("utf-8"), bcrypt.gensalt(14)).
This is because your clearPass is by default an Unicode object and that it can't be directly used in your hashing function, the encode("utf-8") converts it into a standard string and then it can be hashed.
Related
I have a form with counterparty, object and sections i connected them to each other with django-forms-dynamic package but object not connected to sections
Counterparty connected to object form but sections are not connected to object how can i fix that?
I guess that im wrong with 2 functions in forms.py: section_choices and initial_sections and they`re not connected to objects but dont know how to fix that
forms.py
class WorkLogForm(DynamicFormMixin, forms.ModelForm):
def object_choices(form):
contractor_counter = form['contractor_counter'].value()
object_query = ObjectList.objects.filter(contractor_guid__in=[contractor_counter])
return object_query
def initial_object(form):
contractor_counter = form['contractor_counter'].value()
object_query = ObjectList.objects.filter(contractor_guid__in=[contractor_counter])
return object_query.first()
def section_choices(form):
contractor_object = form['contractor_object'].value()
section_query = SectionList.objects.filter(object=contractor_object)
return section_query
def initial_sections(form):
contractor_object = form['contractor_object'].value()
section_query = SectionList.objects.filter(object=contractor_object)
return section_query.first()
contractor_counter = forms.ModelChoiceField(
label='Контрагент',
queryset=CounterParty.objects.none(),
initial=CounterParty.objects.first(),
empty_label='',
)
contractor_object = DynamicField(
forms.ModelChoiceField,
label='Объект',
queryset=object_choices,
initial=initial_object,
)
contractor_section = DynamicField(
forms.ModelMultipleChoiceField,
label='Раздел',
queryset=section_choices,
initial=initial_sections,
)
views.py
#login_required
def create_work_log(request):
if request.method == 'POST':
form = WorkLogForm(request.POST, user=request.user)
if form.is_valid():
work_log = form.save(commit=False)
work_log.author = request.user
work_log = form.save()
messages.success(request, 'Данные занесены успешно', {'work_log': work_log})
return redirect('create_worklog')
else:
messages.error(request, 'Ошибка валидации')
return redirect('create_worklog')
form = WorkLogForm(user=request.user, initial=initial)
return render(request, 'contractor/create_work_log.html', {'form': form})
def contractor_object(request):
form = WorkLogForm(request.GET, user=request.user)
return HttpResponse(form['contractor_object'])
def contractor_section(request):
form = WorkLogForm(request.GET, user=request.user)
return HttpResponse(form['contractor_section'])
This may not be an answer you want but I use HTMX for these things. Here is a link to their example for this.
https://htmx.org/examples/value-select/
There is also a package plugin called Django-htmx.
You may need to learn HTMX but it is a mature technology, rather simple and reliable. I am unfamiliar with Django-forms-dynamic
I am creating a search bar that takes a username and locates that Player in the database. I create a PlayerStatsForm() that takes in the request, searches the database for players with the username from the request, and returns that players stats. I know that the username is being passed by the html form to my python code correctly and the form is passing true for PlayerStatsForm.is_valid() but when I try and call playerstatsform.username it says that the attribute is not found. If I add model = Player and change forms.Form to ModelForm in PlayerStatsForm it tries to insert a player with no username or id into the database and says that the column user_id cannot be null
<tr><th><label for="id_username">Username:</label></th><td><input type="text" name="username" value="testuser" required id="id_username"></td></tr>
Internal Server Error: /elousers/elosearch/
This is the error from the terminal so is the issue that id=id_username and not name=id_username?
playerstatsform:
class PlayerStatsForm(forms.Form):
username = forms.CharField()
class Meta:
fields = (
'username',
)
views.py:
def elosearch(request):
if request.method == 'POST':
print("Post was found")
if 'get_player' in request.POST:
playerstatsform = PlayerStatsForm(request.POST)
print("post found")
if playerstatsform.is_valid():
player = Player.objects.get(name=playerstatsform.cleaned_data['username'])
print("player found successfully")
player_elo = player.elo
player_name = player.name
print(player_elo)
context1 = {'playername': player_name, 'playerelo': player_elo}
return render('elousers/elosearch.html', context1)
else:
invalid_player_entry = "Username not added. Please register below."
context1 = {'invalid_player': invalid_player_entry}
return render(request, 'elousers/elosearch.html', context1)
elif 'addgame' in request.POST:
gameform = GameForm(data=request.POST)
if gameform.is_valid():
gameform.save()
game_success = "Game Successfully Added!"
context2 = {'game_display': game_success}
return render(request, 'elousers/elosearch.html', context2)
else:
game_invalid = "Invalid entry. Please try again."
context2 = {'game_display': game_invalid}
return render(request, 'elousers/elosearch.html', context2)
else:
return render(request, 'elousers/elosearch.html')
elif request.method == 'GET':
print("get was called")
return render(request, 'elousers/elosearch.html')
expect the database to query using the username provided by the form but I am getting 'PlayerStatsForm' object has no attribute 'username'
You can obtain the value from the playerstatsform through the .cleaned_data attribute [Django-doc], which is a dictionary. By using playerstatsform.username, you get access to the form field, but this will render the HTML representation of the field if you pass it through str.
def elosearch(request):
if request.method == 'POST':
print("Post was found")
if 'get_player' in request.POST:
playerstatsform = PlayerStatsForm(request.POST)
if playerstatsform.is_valid():
player = Player.objects.get(name=playerstatsform.cleaned_data['username'])
player_elo = player.elo
player_name = player.name
context1 = {'playername': player_name, 'playerelo': player_elo}
return render(request, 'elousers/elosearch.html', context1)
Note that it is possible that no Player object exists for the given name, or perhaps, if that field is not unique=True, multiple Players can have that name, so you probably should at least try-catch these cases, and handle these accordingly.
You thus probably will need to do something like:
def elosearch(request):
if request.method == 'POST':
print("Post was found")
if 'get_player' in request.POST:
playerstatsform = PlayerStatsForm(request.POST)
if playerstatsform.is_valid():
try:
player = Player.objects.get(
name=playerstatsform.cleaned_data['username']
)
except (Player.DoesNotExist, Player.MultipleObjectsReturned):
player = None
player_elo = None
player_name = None
else:
player_elo = player.elo
player_name = player.name
context1 = {'playername': player_name, 'playerelo': player_elo}
return render(request, 'elousers/elosearch.html', context1)
I currently have a model form that submits an entered domain to the db.
The problem I'm encountering is, I need to save the currently logged in user's ID (PK from the django.auth table) when a domain is submitted to satisfy a PK-FK relationship on the db end.
I currently have:
class SubmitDomain(ModelForm):
domainNm = forms.CharField(initial=u'Enter your domain', label='')
FKtoClient = User.<something>
class Meta:
model = Tld #Create form based off Model for Tld
fields = ['domainNm']
def clean_domainNm(self):
cleanedDomainName = self.cleaned_data.get('domainNm')
if Tld.objects.filter(domainNm=cleanedDomainName).exists():
errorMsg = u"Sorry that domain is not available."
raise ValidationError(errorMsg)
else:
return cleanedDomainName
and views.py
def AccountHome(request):
if request.user.is_anonymous():
return HttpResponseRedirect('/Login/')
form = SubmitDomain(request.POST or None) # A form bound to the POST data
if request.method == 'POST': # If the form has been submitted...
if form.is_valid(): # If form input passes initial validation...
domainNmCleaned = form.cleaned_data['domainNm'] ## clean data in dictionary
clientFKId = request.user.id
form.save() #save cleaned data to the db from dictionary`
try:
return HttpResponseRedirect('/Processscan/?domainNm=' + domainNmCleaned)
except:
raise ValidationError(('Invalid request'), code='300') ## [ TODO ]: add a custom error page here.
else:
form = SubmitDomain()
tld_set = request.user.tld_set.all()
return render(request, 'VA/account/accounthome.html', {
'tld_set':tld_set, 'form' : form
})
The problem is it gives me an error of: (1048, "Column 'FKtoClient_id' cannot be null"), very odd thing happening, for the column FKtoClient, its trying to submit: 7L instead of 7(the PK of this user's record). Any ideas?
If someone can please help, I would really appreciate it
Firstly, remove FKtoClient from your form. You need to set the user in your view where you can yes the request object. It's not possible to set an attribute on the form that automatically sets the current user.
When instantiating your form, you can pass a tld instance which already has the user set.
def AccountHome(request):
# I recommend using the login required decorator instead but this is ok
if request.user.is_anonymous():
return HttpResponseRedirect('/Login/')
# create a tld instance for the form, with the user set
tld = Tld(FKtoClient=request.user)
form = SubmitDomain(data=request.POST or None, instance=tld) # A form bound to the POST data, using the tld instance
if request.method == 'POST': # If the form has been submitted...
if form.is_valid(): # If form input passes initial validation...
domainNm = form.cleaned_data['domainNm']
form.save() #save cleaned data to the db from dictionary
# don't use a try..except block here, it shouldn't raise an exception
return HttpResponseRedirect('/Processscan/?domainNm=%s' % domainNm)
# No need to create another form here, because you are using the request.POST or None trick
# else:
# form = SubmitDomain()
tld_set = request.user.tld_set.all()
return render(request, 'VA/account/accounthome.html', {
'tld_set':tld_set, 'form' : form
})
This has an advantage over #dm03514's answer, which is that you can access the user within form methods as self.instance.user if required.
If you want to Require that a user be logged in to submit a form, you could do something like:
#login_required # if a user iS REQUIRED to be logged in to save a form
def your_view(request):
form = SubmitDomain(request.POST)
if form.is_valid():
new_submit = form.save(commit=False)
new_submit.your_user_field = request.user
new_submit.save()
You can get the logged in user from the request object:
current_user = request.user
In the Django app I am building I would like to have the user creation process go as follows: As user signs up, if valid is then redirected to create a LIST object, and if valid is then redirected to what will be a dashboard for the LIST object just created. My views.py are as follows:
def user_signup(request):
if request.method == 'POST':
form = forms.UserSignupForm(data=request.POST)
if form.is_valid():
user = form.save()
g = Group.objects.get(name='test_group')
g.user_set.add(user)
# log user in
username = form.cleaned_data['username']
password = form.cleaned_data['password1']
user = authenticate(username=username, password=password)
login(request, user)
messages.success(request, u'Welcome to Social FollowUp')
return redirect('user_create')
else:
form = forms.UserSignupForm()
return TemplateResponse(request, 'user_signup.html', {
'form': form,
})
#login_required
#permission_required('')
def user_create(request):
if request.method == 'POST':
list_form = forms.ListForm(request.POST)
if list_form.is_valid():
list_create = list_form.save()
messages.success(request, 'List {0} created'.format(list_create.list_id))
return redirect('user_dashboard')
else:
list_form = forms.ListForm()
return TemplateResponse(request, 'dashboard/create.html', {'list_form': list_form, })
def user_dashboard(request, list_id):
try:
list_id = models.List.objects.get(pk=list_id)
except models.List.DoesNotExist:
raise Http404
return TemplateResponse(request, 'dashboard/view.html', {'list_id': list_id})
My urls.py for these views is as follows:
url(r'user/signup/$', views.user_signup, name='user_signup'),
url(r'u/dashboard/(?P<list_id>\d+)/$', views.user_dashboard, name='user_dashboard'),
url(r'u/list/create/$', views.user_create, name='user_create'),
When I try to run through the process, the first two views work correctly. However when I redirect to the user_dashboard I get the following error:
Reverse for 'user_dashboard' with arguments '' and keyword arguments '{}' not found.
which sites this:
return redirect('user_dashboard')
I'm assuming this has something to do with me not passing in a list_id, however, even when I tried to pass in a hardcoded value it did not work (like this):
return redirect('user_dashboard', {'list_id': 2})
What am I doing wrong here?
Try:
return redirect(reverse('user_dashboard', args=(2,)))
Your code
return redirect('user_dashboard')
would not work because in your url pattern, you have
url(r'u/dashboard/(?P<list_id>\d+)/$', views.user_dashboard, name='user_dashboard'),
which requires list_id as a parameter.
G'day there. I've currently got a bit of an annoyance more than anything. The code below works fully, as expected. Basically it's a ModelForm that dynamically bases it's model on a string received in the url, or based on the class of an instance if that's provided.
My question is whether it's possible to abstract this out into another module, forms.py, by passing the model_name variable. I can pass model_name to the form Class no problems, but I can't figure out how to pass it to Meta after that. Is there any easy way to do this? If not this'll do, but it would make my view code heaps neater.
#user_passes_test(lambda u: u.is_staff, login_url="%slogin/" % NINJA_ADMIN_URL_PREFIX)
def content_form(request, model_name=None, edit=False, call_name=''):
if edit:
content = Content.objects.get(call_name=call_name)
model_name = content.fields.__class__.__name__
class ContentForm(forms.ModelForm):
parent = ModelTextField(queryset=Content.objects.all(), widget=JQueryAutocomplete(
source_url='%sjson/call_names.json' % NINJA_ADMIN_URL_PREFIX, jquery_opts = {'minLength': 2},
override_label='item.fields.call_name', override_value='item.fields.call_name'),
required=False)
class Meta():
model = get_ninja_type(model_name)
widgets = {
'ninja_type': forms.widgets.HiddenInput(),
}
def clean_parent(self):
call_name = self.cleaned_data['parent']
if call_name:
try:
parent = Content.objects.get(call_name=call_name)
except Content.DoesNotExist:
raise forms.ValidationError("The call name '%s' doesn't exist. Choose another parent." % call_name)
return parent
else:
return None
if request.method == 'POST':
if edit:
form = ContentForm(request.POST, instance=content.fields)
else:
form = ContentForm(request.POST)
if form.is_valid():
content = form.save()
messages.success(request, "Your new content has been saved.")
return HttpResponseRedirect('%scontent/' % NINJA_ADMIN_URL_PREFIX)
else:
if edit:
form = ContentForm(instance=content.fields)
else:
form = ContentForm(initial={'ninja_type': model_name.lower(),
'author': request.user})
if edit:
page_title = 'Edit %s' % model_name
else:
page_title = 'Create New %s' % model_name
return render(request, 'ninja/admin/content_form.html', {
'form': form,
'ninja_type': model_name,
'page_title': page_title,
'edit': edit,
'meta_field_names': NINJA_META_FIELD_NAMES,
})
The answer was pretty obvious when I thought about it. A function returning a class works fine. This is what's left at the start of views.py. I'm thinking this is likely the best way to do this, or at least the most concise.
#user_passes_test(lambda u: u.is_staff, login_url="%slogin/" % NINJA_ADMIN_URL_PREFIX)
def content_form(request, model_name=None, edit=False, call_name=''):
if edit:
content = Content.objects.get(call_name=call_name)
model_name = content.fields.__class__.__name__
ContentForm = get_content_form(model_name)
if request.method == 'POST':
if edit:
form = ContentForm(request.POST, instance=content.fields)
else:
This is the forms.py entry.
def get_content_form(model_name):
class DynamicContentForm(forms.ModelForm):
parent = ModelTextField(queryset=Content.objects.all(), widget=JQueryAutocomplete(
source_url='%sjson/call_names.json' % NINJA_ADMIN_URL_PREFIX, jquery_opts = {'minLength': 2},
override_label='item.fields.call_name', override_value='item.fields.call_name'),
required=False)
class Meta():
model = get_ninja_type(model_name)
widgets = {
'ninja_type': forms.widgets.HiddenInput(),
}
def clean_parent(self):
call_name = self.cleaned_data['parent']
if call_name:
try:
parent = Content.objects.get(call_name=call_name)
except Content.DoesNotExist:
raise forms.ValidationError("The call name '%s' doesn't exist. Choose another parent." % call_name)
return parent
else:
return None
return DynamicContentForm