Django Chat App - Capturing value from URL - django

I tried to create a simple Django Chat App. There is no login system.
Whenever a user(e.g. John) tries to create a message, it stores under 'messageroom'
I tried to pass the username 'John' value in the URL but somehow it is not creating a message as expected.
Here is my code
Urls.py :
urlpatterns = [
path('admin/', admin.site.urls),
path('',views.home,name='home'),
path('checkview',views.checkview,name='checkview'),
path('messageroom/<str:room_name>/<str:username>',views.messageroom,name='messageroom'),
]
Models.py
class Room(models.Model):
roomname = models.CharField(max_length=1000)
class Message(models.Model):
messagetext = models.CharField(max_length=10000)
username = models.CharField(max_length=1000)
datetime = models.DateTimeField(default=datetime.now,blank=True)
messageroom = models.CharField(max_length=1000)
Views.py
def home(request):
return render(request,'home.html',{})
def checkview(request):
room_name=request.POST.get('room_name')
username = request.POST.get('username')
Roomexists = Room.objects.filter(roomname=room_name)
if Roomexists.exists():
return redirect('messageroom/'+room_name+'/'+username)
else:
newroom = Room(roomname=room_name)
newroom.save()
return redirect('messageroom/'+room_name+'/'+username)
def messageroom(request,room_name,username):
if request.method == "POST":
messagetext = request.POST.get('message')
newmessage = Message(messagetext=messagetext,messageroom=room_name,username=username)
newmessage.save()
listmessages = Message.objects.filter(messageroom=room_name)
return render(request, 'room.html', {'listmessages':listmessages,'room_name':room_name,'username':username})
Room.html
<form id="post-form2" method="POST" action="messageroom">
{% csrf_token %}
<input type="text" name="message" id="message" width="100px" />
<input type="submit" value="Send">
</form>
I want to create messages under the user which should be there on the URL.

you should pass values in urls in html form like this....
<form id="post-form2" method="POST" action="{% url 'messageroom' room_name username %}">
{% csrf_token %}
<input type="text" name="message" id="message" width="100px" />
<input type="submit" value="Send">
</form>
-------------------------- OR ------------------
<form id="post-form2" method="POST" action="/messageroom/room_name/username/">
{% csrf_token %}
<input type="text" name="message" id="message" width="100px" />
<input type="submit" value="Send">
</form>

Related

Django add data to database from HTML page

Every applicant should enter their data from HTML page and this datas must insert to database. I think I did everything right, but datas are not shown in database. Here are my codes.
models.py:
class Applicant(models.Model):
name = models.CharField(max_length=20)
surname = models.CharField(max_length=30)
phone = models.CharField(max_length=15)
email = models.EmailField(max_length=40)
motivation_letter = models.TextField(max_length=200)
def __str__(self):
return self.name
views.py:
def apply(request):
if request.method == "POST":
if request.POST.get('motivation_letter'):
applicant = Applicant()
applicant.name = request.POST.get('name')
applicant.surname = request.POST.get('surname')
applicant.phone = request.POST.get('phone')
applicant.email = request.POST.get('email')
applicant.motivation_letter = request.POST.get('motivation_letter')
applicant.save()
return render(request, 'index.html')
HTML:
<form method="POST">
{% csrf_token %}
<label>Ad</label><br />
<input type="text" name="name"><br />
<label>Soyad</label><br />
<input type="text" name="surname"><br />
<label>Telefon nömrəsi</label><br />
<input type="number" name="phone"><br />
<label>Elektron poçt</label><br />
<input type="email" name="email"><br />
<label>Something else</label><br />
<textarea class="smth-else-textarea" cols="30" rows="10" name="motivation_letter"></textarea><br />
<input type="submit" value="Göndər" class="apply-button"/>
</form>
You should use model_name.objects.create(xx=something..) to insert data.
def apply(request):
if request.method == "POST":
if request.POST.get('motivation_letter'):
Applicant.objects.create(
name = request.POST.get('name'),
surname = request.POST.get('surname'),
phone = request.POST.get('phone'),
email = request.POST.get('email'),
motivation_letter = request.POST.get('motivation_letter'))
return render(request, 'index.html')
html : (if you don't work , try it : app_name:apply)
<form action="{% url "apply" %}" method='POST' > {% csrf_token %}
<label>Ad</label><br />
<input type="text" name="name"><br />
<label>Soyad</label><br />
<input type="text" name="surname"><br />
<label>Telefon nömrəsi</label><br />
<input type="number" name="phone"><br />
<label>Elektron poçt</label><br />
<input type="email" name="email"><br />
<label>Something else</label><br />
<textarea class="smth-else-textarea" cols="30" rows="10"
name="motivation_letter"></textarea><br />
<input type="submit" value="Göndər" class="apply-button"/>
</form>
urls.py: (not : import your views)
path('apply/', views.apply , name='apply'),

Is this the wrong logic for image uploading with django? form.is_valid = false

I am really new to django, and I'm not sure I completely understand how forms work or how to use them. I've been looking through a couple tutorials concering file-uploading, but there are a lot of different ways it seems. I'll just include the whole process from top to bottom.
I get a 500 error, because form.is_valid does not return true.
I'll be really gratefull for any help/tips :)
profile.html
<form role="form" enctype="multipart/form-data" ng-submit="profile.upload_picture()">
<input id="id_image" type="file" class="" name="image" ng-model="profile.image">
<input type="hidden" value="{{ profile.user.email }}" ng-model="profile.email">
<button type="submit" class="btn btn-primary">Submit</button>
</form>
ProfileController.js
function upload_picture() {
ProfileHandler.setProfilePicture(vm.image, vm.email);
}
ProfileHandler.js
function setProfilePicture(profile_pic, email) {
return $http.post('/api/v1/profile/picture/', {
profile_pic: profile_pic,
email: email
}).then(imageSuccessFn, imageErrorFn);
}
ProfilePictureView
class ProfilePictureView(views.APIView):
def post(self, request):
if request.method == 'POST':
form = ProfileImageForm(request.POST, request.FILES)
if form.is_valid():
str_data = request.body.decode('utf-8')
data = json.loads(str_data)
email = data.get('email', None)
acc = Account.objects.get(email=email)
acc.model_pic = form.cleaned_data['image']
acc.save()
return Response({
'status': 'Accepted',
'message': 'Image uploaded.'
}, status=status.HTTP_202_ACCEPTED)
else:
return Response({
'status': 'Internal server error',
'message': 'Form not valid'
}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
else:
return Response({
'status': 'Method not allowed',
'message': 'Only post is accepted'
}, status=status.HTTP_405_METHOD_NOT_ALLOWED)
ProfileImageForm
class ProfileImageForm(forms.Form):
image = forms.FileField(label='Select a profile Image')
AccountModel
class Account(AbstractBaseUser):
....
image = models.ImageField(upload_to='profile_images', blank=True)
....
Urls (excluded some urls)
urlpatterns = patterns(
'',
url(r'^api/v1/', include(router.urls)),
.....,
url(r'^api/v1/profile/picture/$', ProfilePictureView.as_view(), name='profile'),
url('^.*$', IndexView.as_view(), name='index'),
) + static(settings.MEDIA_URL, document_root=settings.MEDIA_URL);
Settings.py
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
MEDIA_URL = '/media/'
You don't have a csrf token input in your form (documentation). Also, add method="post" attribute to the form.
<form role="form" method="post" enctype="multipart/form-data" ng-submit="profile.upload_picture()">
{% csrf_token %}
<input id="id_image" type="file" class="" name="image" ng-model="profile.image">
<input type="hidden" value="{{ profile.user.email }}" ng-model="profile.email">
<button type="submit" class="btn btn-primary">Submit</button>
</form>
You need to add {% csrf_token %} in your form in the profile.htm file.
<form>
{% csrf_token %}
</form>
What this line will do is to add an hidden input field inside your form which contains a token. The token is submitted along with the form, and Django automatically checks the value of the token to see if this post request is actually coming from your "frontend" rather than somebody else's.
Also, add method="post":
<form method="post">
</form>

Using <form> to update BooleanField in Django

Using Django 1.6 with Python 2.7.
My model has a BooleanField variable, and I want the user to be able to change this via POST by clicking a button to change it from False to True, or vice versa. Having issues rendering the template.
Model currently:
class Pic(models.Model):
Name = models.CharField(max_length=100)
Good = models.BooleanField()
Image = models.FileField(upload_to="images/")
def __unicode__(self):
return self.Name
App urls is:
url(r'^(?P<Pic_id>\d+)/$', views.single_picture, name='single_picture'),
In the template I have:
<form action="{% url 'single_picture' Pic.Good %}" method="post">
{% csrf_token %}
{% if Pic.Good %}
<input type="checkbox" name="choice" id="{{ Pic.Good }}" value="False" />
<label for="{{ Pic.Good }}">False</label><br />
{% else %}
<input type="checkbox" name="choice" id="{{ Pic.Good }}" value="True" />
<label for="{{ Pic.Good }}">True</label><br />
{% endif %}
<input type="submit" value="good" />
</form>
And for my view I have:
def single_picture(request, Pic_id):
if request.method == 'GET':
pic = get_object_or_404(Pic, pk=Pic_id)
latest_pictures_list = Pic.objects.all()
return render(request, 'pictures/single_picture.html', {'Pic': pic, 'latest_pictures_list': latest_pictures_list})
elif request.method == 'POST':
pic = get_object_or_404(Pic, pk=Pic_id)
latest_pictures_list = Pic.objects.all()
try:
selected_choice = p.choice_set.get(pk=request.POST['choice'])
except (KeyError, Pic.DoesNotExist):
return render(request, 'pictures/single_picture.html', {'Pic': pic, 'error_message': 'uhhhh...',
})
else:
selected_choice.save()
return HttpResponseRedirect(reverse('pictures/single_picture.html', {'Pic': pic}))
I'm not sure if there are multiple errors at this point or not. Currently when trying to view the template, I get
Reverse for 'single_picture' with arguments '(True,)' and keyword arguments '{}' not found. 0 pattern(s) tried: []
for the '< form >' line. I'm guessing it's to do with my View?
I think the issue is in your template, in the line
<form action="{% url 'single_picture' Pic.Good %}" method="post">
Your regex in urls.py is r'^(?P<Pic_id>\d+)/$', I'm guessing that it's expecting the id of the Picobject you return in the GET request and not a boolean, in which case the line should be
<form action="{% url 'single_picture' Pic.id %}" method="post">
Likewise, in the lines underneath, there isid="{{ Pic.Good }}" which will display as HTML as id=True or id=False, which I suppose you don't want. You need to replace that bit by id="{{Pic.id}}"

How to put login and registration form on same index page

As of now, I have my registration form and my log in form on two different pages, I can't seem to put them in one view because the way I did it, the views require different return statements. So here is my registration view function:
def register_user(request):
if request.method == 'POST':
form = MyRegistrationForm(request.POST)
if form.is_valid():
form.save()
return HttpResponseRedirect('/accounts/register_success')
args = {}
args.update(csrf(request))
args['form'] = MyRegistrationForm()
return render_to_response('register.html', args)
def register_success(request):
return render_to_response('register_success.html')
and here is my log in and authentication view:
def login(request):
c = {}
c.update(csrf(request))
return render_to_response('login.html', c)
def auth_view(request):
username = request.POST.get('username', '')
password = request.POST.get('password', '')
user = auth.authenticate(username=username, password=password)
if user is not None:
auth.login(request, user)
return HttpResponseRedirect('/accounts/loggedin')
else:
return HttpResponseRedirect('/accounts/invalid')
Here is the template for the log in page:
<form action="/accounts/auth/" method="post">{% csrf_token %}
<label for="username">User name:</label>
<input type="text" name="username" value="" id="username">
<label for="password">Password:</label>
<input type="password" name="password" value="" id="password">
<input type="submit" value="login" />
</form>
and here is the template for the registration page:
<h2>Register</h2>
<form action="/accounts/register/" method="post">{% csrf_token %}
{{form}}
<input type="submit" value="Register" />
</form>
Again, I can't seem to put them together because the views have to return different things.. any idea on how to do it?
EDIT: This is my urls.py:
url(r'^admin/', include(admin.site.urls)),
url(r'^$', index),
url(r'^accounts/auth/$', auth_view),
url(r'^invalid/$', invalid_login),
url(r'^accounts/register/$', register_user),
url(r'^accounts/register_success/$', register_success),
so it will only use the register_user view if the url is accounts/register, I want it to user the register_view view if it is the homepage (^$). My index view is this:
def index(request):
c = {}
c.update(csrf(request))
return render_to_response('index.html', c)
it basically just adds a csrf token to my index.html (log in template, as seen above). This is why I want to be able to somehow merge index and the register_user view, since register_user view calls the actual form = MyRegistrationForm(request.POST) which is used in the registration template (the registration template uses {{form}}
If you just want to show login and registration on the same page. Create a html page with two forms. Action of one of them to url '/accounts/register/' and another one to '/accounts/auth/'.
for example, change your register.html to:
<html>
<head><body>
<form action="/accounts/auth/" method="post">{% csrf_token %}
<label for="username">User name:</label>
<input type="text" name="username" value="" id="username">
<label for="password">Password:</label>
<input type="password" name="password" value="" id="password">
<input type="submit" value="login" />
</form>
<h2>Register</h2>
<form action="/accounts/register/" method="post">{% csrf_token %}
{{form}}
<input type="submit" value="Register" />
</form>
</body>
</html>
When submit the form, it will go to corresponding view and redirect based on that view.
EDIT:To pass a MyRegistrationForm instance you can update the index view as follows:
def index(request):
c = {}
c.update(csrf(request))
c.update({'form':MyRegistrationForm()})
return render_to_response('index.html', c)
use the login.html as above html code in the answer.
You can do this with a help of little Javascript. Let's create a input field first:
<input type="hidden" name="button-name" id="button-name" value="" />
<input type="submit" name="register-button" id="register-button" onclick="changeValue()" />
function changeValue(){
document.getElementById('button-name').value="register"
}
Now, in your views do this:
button_name = request.POST['button-name']
if button-name=='register':
# Do the registration
# Redirect to another view or template
else:
# Do your login thing
# Redirect where you want

#login_decorator not working as expected in Django?

I am using #login_decorator('/login/') in every view. Whenever I tried to access other URL it redirects to the login page. The URL turns like this:
http://127.0.0.1:8000/login/?next=/upload_file/
Now, when I enter correct username, password and click Submit, nothing is happening. I am still on the same page with the same URL.
Here's my form.html:
<form action="/login/" method="post">
{% csrf_token %}
Username: <input type="text" name="username" />
Password: <input type="password" name="password" />
<input type="Submit">
Views.py:
def login_upload(request):
try:
if request.method == 'POST':
usern = request.POST['username']
unames = ''.join(usern)
passwo = request.POST['password']
s = ''.join(passwo)
h = hashlib.sha1(s).hexdigest()
db = MySQLdb.connect(user='root', db='galaxy', passwd='devil', host='localhost')
cursor = db.cursor()
cursor.execute("SELECT id, username, password FROM galaxy_user where username=%s and password=%s", (unames, h))
id, compareu, comparep = zip(*cursor.fetchall())
db.close()
return HttpResponseRedirect('/upload_file/')
except ValueError:
return render_to_response('login.html', context_instance=RequestContext(request))
urls.py:
urlpatterns = patterns('',
url(r'^admin/', include(admin.site.urls)),
url(r'^upload_file/', 'fileupload.views.upload_file'),
url(r'^sync/', 'fileupload.views.sync'),
url(r'^login_upload/', 'fileupload.views.login_upload'),
url(r'^upload_file_form', 'fileupload.views.upload_file_form' ),
url(r'^book_list', 'fileupload.views.book_list'),
url(r'^backend/', 'fileupload.backend.show_files')
)
You need to put "next" value in your form
<form action="/login/" method="post">
{% csrf_token %}
Username: <input type="text" name="username" />
Password: <input type="password" name="password" />
<input type="hidden" name="next" value="{{ next }}" />
<input type="Submit">