Websocket connection failed: With django and vue.js - django

I'm trying to set up websockets to show any new entry in Post model (I'm new with websockets)
class Post(models.Model):
title = models.CharField(max_length=200, unique=True)
content = models.TextField()
status = models.IntegerField(choices=STATUS, default=0)
author = models.ForeignKey(
User,
related_name="blog_posts",
on_delete=models.CASCADE,
)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
This is the consumers.py
class PostConsumer(ListModelMixin, GenericAsyncAPIConsumer):
queryset = Post.objects.all()
serializer_class = PostSerializer
permissions = (permissions.AllowAny,)
For checking if it works I have an html and I'm handling the websockets with vue.js
here's the more relevant part of the index.html
<title>Testing Websockets</title>
</head>
<body>
<div id="app" class="row mt-5">
<div class="col-1"></div>
<div class="col-10">
<div class="card">
<p class="card-header">Display list of all the posts in Real-Time</p>
<div class="card-body">
<table class="table align-middle mb-0 bg-white">
<thead class="bg-light">
<tr>
<th>Title</th>
<th>Status</th>
<th>Author</th>
</tr>
</thead>
<tbody>
<tr v-for="post in posts">
<td>
<p class="fw-normal mb-1">[[ post.title ]]</p>
</td>
<td>
<span
class="badge rounded-pill d-inline"
:class="{'bg-success': post.status !== 'Draft', 'bg-warning': post.status === 'Draft'}"
>
[[ post.status ]]
</span>
</td>
<td>[[ post.author ]]</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
<script
src="https://code.jquery.com/jquery-3.6.0.min.js"
integrity="sha256-/xUj+3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4="
crossorigin="anonymous"
></script>
<!-- JavaScript Bundle with Popper -->
<script
src="https://cdn.jsdelivr.net/npm/bootstrap#5.2.0/dist/js/bootstrap.bundle.min.js"
integrity="sha384-A3rJD856KowSb7dwlZdYEkO39Gagi7vIsF0jrRAoQmDKKtQBHUuLZ9AsSv4jD4Xa"
crossorigin="anonymous"
></script>
<script src="https://cdn.jsdelivr.net/npm/vue#2.6.14"></script>
<script>
vueApp = new Vue({
el: "#app",
delimiters: ["[[", "]]"],
data() {
return {
posts: [],
};
},
});
var ws = new WebSocket("ws://localhost:8001/ws/");
console.log(this.posts, "CHECKING WEBSOCKETS")
console.log(ws)
ws.onopen = function (e) {
ws.send(
JSON.stringify({
action: "list",
request_id: new Date().getTime(),
})
);
};
ws.onmessage = function (e) {
allData = JSON.parse(e.data);
if (allData.action === "list") {
vueApp.$data.posts = allData.data;
vueApp.$forceUpdate();
} else if (allData.action === "create") {
vueApp.$data.posts.push(allData.data);
}
};
</script>
</body>
</html>
async def connect(self, **kwargs):
await self.model_change.subscribe()
await super().connect()
#model_observer(Post)
async def model_change(self, message, observer=None, **kwargs):
await self.send_json(message)
#model_change.serializer
def model_serialize(self, instance, action, **kwargs):
return dict(data=PostSerializer(instance=instance).data, action=action.value)
when I run the in the console logs I see the following message
WebSocket connection to 'ws://localhost:8001/ws/' failed:
Please let me know if there's anything else that I need to share.
EDIT:
I followed this youtube tutorial

I had a tricky mistake. This is what I had in my settings.py
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'rest_framework',
'user',
'rest_framework_simplejwt',
'channels',
'daphne',
]
I moved channels and daphne to the top of the list and it worked. Like this
INSTALLED_APPS = [
'channels',
'daphne',
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'rest_framework',
'user',
'rest_framework_simplejwt',
]

Related

django_filters - Filters are not responsive (function based view)

Trying to implement a filter django_filters to an existing function based view.
The filter is rendering as it should, but nothing is happening.
There is a few question on the topic, so I am going to answer some potential questions:
I used $ pip install django-filter
I installed in my virtual environment
Filter.py is installed in the same app as the views
Something to mention in my filters.py, import django_filters is underlined in red ("Import "django_filters" could not be resolved"). I cant find why, but this could be a strong contender in the root cause of the problem.
Settings file
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
"crispy_forms",
'main.apps.MainConfig',
'django_filters',
models
class Catalogue(models.Model):
product = models.ManyToManyField('Product', blank=True)
product_title = models.TextField('Product Title', blank=True)
class Meta:
db_table='Catalogue'
def __str__(self):
return str(self.product_title)
filters
import django_filters
from .models import *
class CatalogueFilter(django_filters.FilterSet):
class Meta:
model = Catalogue
fields = ['product_title']
views
from .filters import CatalogueFilter
def show_venue(request, venue_id):
if request.method == "POST" and 'btnreview_form' in request.POST:
form = CatalogueReviewForm(request.POST)
if form.is_valid():
data = form.save(commit=False)
data.product_id = venue_id # links to product ID in Catalogue Model and return product name
data.venue_id = request.POST.get('venue_id') # prints venue ID in form
data.user_id = request.user.id
data.save()
ven_id = request.POST.get('venue_id')
print(data)
form.save()
return HttpResponseRedirect(ven_id)
else:
venue = Venue.objects.get(pk=venue_id)
menu = Catalogue.objects.filter(venue=venue_id)
categories = Catalogue.objects.filter(venue=venue_id).order_by('category_order')
myFilter = CatalogueFilter(request.GET, Catalogue.objects.filter(venue=venue_id).order_by('category_order'))
template (I added a bit more than the basic code, as I am thinking the use of the table could be the problem)
{% if not menu.all %}
No menu available.
{% else %}
<form method="get">
{{myFilter.form}}
<button class ="btn btn-primary" type="submit">
</form>
</br>
{% regroup categories by category_menu as category_menu_list %}
{% for category_menu in category_menu_list %}
<table class="table">
<tr>
<th></th>
<th>
{{category_menu.grouper}}
</th>
</tr>
{% for catalogue in category_menu.list %}
<tr>
<td>{{catalogue.product_title}}
</br>
<div class="d-flex flex-column mt-4">
<a class="button3 btn-block mybtn tx-tfm" href="{% url 'show-product-from-venue' catalogue.id %}?next={{ request.path|urlencode}}">Review</a>
</div>
</td>
<td>
</td>
</tr>
{%endfor%}
</table>
{%endfor%}
{%endif%}
requirements
django-filter==22.1
You need to add qs with filter like this
else:
venue = Venue.objects.get(pk=venue_id)
menu = Catalogue.objects.filter(venue=venue_id)
categories = Catalogue.objects.filter(venue=venue_id).order_by('category_order')
myFilter = CatalogueFilter(request.GET, ,queryset=categories)
categories = myFilter.qs

How do I fix the error that django keeps giving me when I try to click to update my form?

I have tried many different ways, including class based views to make a user able to edit the form they completed. I get the same error no matter what I try and can't get to the bottom of it. I tried to post just enough code below so it is readable. Here are the errors:
Exception Type: NoReverseMatch
Exception Value:
Reverse for 'update' with arguments '('',)' not found. 1 pattern(s) tried: ['update/(?P[^/]+)/$']
Exception Location: /Users/name/Desktop/Django/env/lib/python3.9/site-packages/django/urls/resolvers.py in _reverse_with_prefix, line 677
In template /Users/name/Desktop/Django/dv_project/myapp/templates/base.html, error at line 12
models.py
class StepOne(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, null=True)
title = "STEP 1: Safety during a violent incident"
box1 = models.CharField(max_length=100, null=True)
box2 = models.CharField(max_length=100, null=True)
box3 = models.CharField(max_length=100, null=True)
box4 = models.CharField(max_length=100, null=True)
box5 = models.CharField(max_length=100, null=True)
box6 = models.CharField(max_length=100, null=True)
def __str__(self):
return self.title class StepOne(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, null=True)
title = "STEP 1: Safety during a violent incident"
box1 = models.CharField(max_length=100, null=True)
box2 = models.CharField(max_length=100, null=True)
box3 = models.CharField(max_length=100, null=True)
box4 = models.CharField(max_length=100, null=True)
box5 = models.CharField(max_length=100, null=True)
box6 = models.CharField(max_length=100, null=True)
def __str__(self):
return self.title
forms.py
class StepOneForm(forms.ModelForm):
box1 = forms.CharField()
class Meta:
model = StepOne #which model we want to use as a model for our model form
fields= ("box1","box2","box3", "box4", "box5", "box6")
views.py
from django.shortcuts import render, redirect
from django.contrib import messages
from .forms import StepOneForm
from .models import StepOne, CreateUserForm
from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth import authenticate, login, logout
from django.contrib.auth.models import User
from django.contrib.auth.decorators import login_required
def update(request, id):
data = get_object_or_404(StepOne, id=id)
form = StepOneForm(instance=data)
if request.method == "POST":
form = StepOneForm(request.POST, instance=data)
if form.is_valid():
form.save()
return redirect ('user-homepage')
context = {
"form":form,
"data": data
}
return render(request, 'shell_test', context)
def loginPage(request):
if request.method == "POST": #The user entered the info and logged in.
username = request.POST.get('username') #this is sent from the front end through the login.html.
password = request.POST.get('password')
try:
user= User.objects.get(username=username)
except:
messages.error(request, "User does not exist.")
user = authenticate(request, username=username, password=password) #if get was successful authenticate user.
if user is not None: #if we got a user
login(request, user) #will add the session in the database and browser.
return redirect('user-homepage')
else:
messages.error(request, "Username or password does not exist.")
context = {}
return render(request, 'registration/login_registration.html', context)
def logoutUser(request):
logout(request) # deletes the token/user session
return redirect('welcome')
#login_required(login_url='login_user')
def Step1_Form_Completion(request):
"""Generates link for user to fill out form"""
form = StepOneForm #Assign the form to the variable in the function.
if request.method == 'POST': # if method or form is requested then POST or send data to this function. If someone is loggded in . .
try:
form = StepOneForm(request.POST) #the method is form and it is to be posted.
if form.is_valid(): #if the form is django's definiton for 'valid' then save it and redirect the user home.
form.instance.user= request.user
form.save()
return redirect('user-homepage')
except:
messages.success(request, 'Cannot resubmit. Please use "edit" instead.')
return redirect('user-homepage')
return render(request, 'form.html', {'form':form} ) # return this function to the form.html page and let it use form as s variable and call it's attributes (form.box1)
#login_required(login_url='login_user') #sends user back to login page if they try to go to a view form.
def Step1_Form_View(request):
"""View for user to see completed form"""
step1 = StepOne.objects.filter(user=request.user) #user can only view there form. request user and filter the objects/forms for there step oneform.
return render(request,'form_view.html',{'step1': step1})
def index(request):
return render(request, 'index.html')
def register_user(request):
form = UserCreationForm()
if request.method == 'POST': #if someone has filled out a form do something.
form = UserCreationForm(request.POST)
if form.is_valid():
form.save()
username = form.cleaned_data['username']
password = form.cleaned_data['password1']
password2 = form.cleaned_data['password2']
user = authenticate(username=username, password=password) #authenticate user
login(request, user) #log user in
messages.success(request, 'Registration Successful')
return redirect('user-homepage')
else:
messages.success(request, 'Already Registered, please log in.')
return render(request, 'registration/register_user.html', {'form': form} )
def shellTesting(request):
thing = StepOne.objects.get(user=request.user)
return render(request, 'shell_test.html', {'thing': thing})
def welcome(request):
return render(request, 'welcome.html')
def base(request):
return render(request, 'base.html')
urls.py
path('update/<str:id>/', views.update, name='update'),
index.html
<!-- This is the page that the link to editable the form is located, I only put the code for the button to make it shorter -->
Edit
forms.html
{% block content %}
</head>
<body>
<form method='post'>
{% csrf_token %}
STEP 1: Safety during a violent incident. I will not always be able to avoid violent incidents. In order to increase safety I may use a variety of strategies.
I can use some of the following strategies:
<p>
A. If I decide to leave, I will {{ form.box1 }}. (Practice how to get out safely. What doors, windows, elevators, stairwells, or fire escapes would you use?)
<p>
B. I can keep my purse and car keys ready and put them (location) {{ form.box2 }} in order to leave quickly.
</p>
<p>
C. I can tell {{ form.box3 }} about the violence and request that she or he call the police if she or he hears suspicious noises coming from my house.
</p>
<p>
D. I can teach my children how to use the telephone to contact the police, the fire department, and 911. E. I will use {{ form.box4 }} as my code with my children or my
friends so they can call for help.
</p>
<p>
F. If I have to leave my home, I will go to {{ form.box5 }}. (Decide this even if you don’t think there will be a next time.)
<p>
G. I can also teach some of these strategies to some or all of my children.
</p>
<p>
H. When I expect we’re going to have an argument, I’ll try to move to a place that is low risk, such as {{ form.box6 }}. (Try to avoid arguments in the bathroom, garage, kitchen, near weapons, or in rooms without access to an outside door.)
</p>
<p>
I. I will use my judgment and intuition. If the situation is very serious, I can give my partner what he/she wants to calm him/her down.
</p>
<button type="submit">Submit</button>
</form>
</body>
</html>
{% endblock content %}
base.html
{% load static %}
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" type="text/css" href="{% static 'website/style.css' %}">
<!-- The line and href below are really important it formats the navbar and makes the "container" gutter work. -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap#5.2.0/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-gH2yIJqKdNHPEq0n4Mqa/HGKIhSkIHeL5AyhkYV8i59U5AR6csBvApHHNl/vI1Bx" crossorigin="anonymous">
<title>DV_Form</title>
</head>
<body>
{% include 'navbar.html' %}
<br/>
<div class="container"> <!--creates a gutter for content on homepage, this is good.-->
{% if messages %}
<ul class="messages">
{% for message in messages %}
<div class="alert alert-warning alert-dismissible fade show" role="alert">
<strong>{{message}}</strong> <!-- could write message here -->
<!-- <button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button> -->
</div>
{% endfor %}
</ul>
{% endif %}
{% block content %}
{% endblock %}
</div>
</body>
</html>
index.html
{% extends 'base.html' %}
{% block content %}
<!--Row -->
<div class="container">
<div class="row">
<div class="col-md-auto">
Step 1: A Violent Incident
</div>
<div class="col-md-auto">
Form
</div>
<div class="col-sm-auto">
View
</div>
<div class="col-sm-auto">
Edit
</div>
</div>
{% endblock %}
welcome.html
{% load static %}
{% include 'navbar.html' %}
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" type="text/css" href="{% static 'website/style.css' %}">
<!-- The line and href below are really important it formats the navbar and makes the "container" gutter work. -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap#5.2.0/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-gH2yIJqKdNHPEq0n4Mqa/HGKIhSkIHeL5AyhkYV8i59U5AR6csBvApHHNl/vI1Bx" crossorigin="anonymous">
</head>
<body>
<br/>
<div class="container"> <!--creates a gutter for content on homepage, this is good.-->
<h1>Welcome!</h1>
<h3>Please register below or log in above.</h3>
<h7>This website has security features built-in. However, by creating account you are
accepting responsbility for how it is used and who has access to it through your devices.</h7><p>
<p><p>Register Here!</p>
</div>
<div>
{% block content %}
{% endblock %}
</div>
</body>
</html>
<html>
<head>
<title>Login</title>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.6.1/css/all.css" integrity="sha384-gfdkjb5BdAXd+lj+gudLWI+BXq4IuLW5IT+brZEZsLFm++aCMlF1V92rMkPaX4PP" crossorigin="anonymous">
<style>
body,
html {
margin: 0;
padding: 0;
height: 100%;
background: purple !important;
}
.user_card {
width: 350px;
margin-top: auto;
margin-bottom: auto;
background: grey;
position: relative;
display: flex;
justify-content: center;
flex-direction: column;
padding: 10px;
box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
-webkit-box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
-moz-box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
border-radius: 5px;
}
.form_container {
margin-top: 20px;
}
#form-title{
color: purple;
}
.login_btn {
width: 100%;
background: purple !important;
color: white !important;
}
.login_btn:focus {
box-shadow: none !important;
outline: 0px !important;
}
.login_container {
padding: 0 2rem;
}
.input-group-text {
background: purple !important;
color: white !important;
border: 0 !important;
border-radius: 0.25rem 0 0 0.25rem !important;
}
.input_user,
.input_pass:focus {
box-shadow: none !important;
outline: 0px !important;
}
#messages{
background-color: grey;
color: #fff;
padding: 10px;
margin-top: 10px;
}
</style>
</head>
<body>
<div class="container h-100">
<div class="d-flex justify-content-center h-100">
<div class="user_card">
<div class="d-flex justify-content-center">
<h3 id="form-title">LOGIN</h3>
</div>
<div class="d-flex justify-content-center form_container">
<form method="POST" action="">
{% csrf_token %}
<div class="input-group mb-3">
<div class="input-group-append">
<span class="input-group-text"><i class="fas fa-user"></i></span>
</div>
{{form.username}}
</div>
<div class="input-group mb-2">
<div class="input-group-append">
<span class="input-group-text"><i class="fas fa-key"></i></span>
</div>
{{form.password1}}
</div>
<div class="input-group mb-2">
<div class="input-group-append">
<span class="input-group-text"><i class="fas fa-key"></i></span>
</div>
{{form.password2}}
</div>
<div class="d-flex justify-content-center mt-3 login_container">
<input class="btn login_btn" type="submit" value="Login">
</div>
</form>
</div>
</div>
</div>
</div>
</div>
<script>
/* Because i didnt set placeholder values in forms.py they will be set here using vanilla Javascript
//We start indexing at one because CSRF_token is considered and input field
*/
//Query All input fields - this javascript just tells the code where to put the 'string'
var form_fields = document.getElementsByTagName('input')
form_fields[1].placeholder='Username..';
form_fields[2].placeholder='Enter password...';
form_fields[3].placeholder='Re-enter Password...';
for (var field in form_fields){
form_fields[field].className += ' form-control'
}
</script>
</body>
</html>
<nav class="navbar navbar-expand-lg bg-light">
<div class="container-fluid">
<!-- Name of NavBar -->
<a class="navbar-brand" href="{% url 'welcome' %}"><h4> DV Plan</h4></a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<ul class="navbar-nav me-auto mb-2 mb-lg-10">
<!-- Link 1 -->
<a class="nav-link active" aria-current="page" href="{% url 'welcome' %}">Homepage</a>
<!-- Only Logged in User can see forms -->
{% if request.user.is_authenticated %}
<a class="nav-link active" aria-current="page" href="{% url 'user-homepage' %}">{{user}}'s Profile</a>
{% else %}
{% endif %}
<!-- Logged in user can see logout button-->
{% if request.user.is_authenticated %}
<a class="nav-link" href="{% url 'logout' %}">Logout</a>
{% else %}
<a class="nav-link" href="{% url 'login_user' %}">Login</a>
{% endif %}
<!-- Dropdown Items
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-expanded="false">
Dropdown
</a>
<ul class="dropdown-menu">
<li><a class="dropdown-item" href="#">Action</a></li>
<li><a class="dropdown-item" href="#">Another action</a></li>
<li><hr class="dropdown-divider"></li>
<li><a class="dropdown-item" href="#">Something else here</a></li>
</ul>
</li> -->
</ul>
<form class="d-flex" role="search">
<input class="form-control me-2" type="search" placeholder="Search" aria-label="Search">
<button class="btn btn-outline-success" type="submit">Search</button>
</form>
</div>
</div>
</nav>
form_view.html
{% include 'navbar.html' %}
<!-- The line and href below are really important it formats the navbar and makes the "container" gutter work. -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap#5.2.0/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-gH2yIJqKdNHPEq0n4Mqa/HGKIhSkIHeL5AyhkYV8i59U5AR6csBvApHHNl/vI1Bx" crossorigin="anonymous">
<body>
{% if step1 %}
<h1>Your Step 1 Plan</h1>
<tr>
{% for st in step1 %}
<p>
A. If I decide to leave, I will <b>{{ st.box1}}</b>. (Practice how to get out safely. What doors, windows, elevators, stairwells, or fire escapes would you use?)
<p>
B. I can keep my purse and car keys ready and put them (location) <b>{{ st.box2 }}</b> in order to leave quickly.
</p>
<p>
C. I can tell <b>{{ st.box3 }}</b> about the violence and request that she or he call the police if she or he hears suspicious noises coming from my house.
</p>
<p>
D. I can teach my children how to use the telephone to contact the police, the fire department, and 911. E. I will use </b>{{ st.box4 }}</b> as my code with my children or my
friends so they can call for help.
</p>
<p>
F. If I have to leave my home, I will go to <b>{{st.box5}}</b>. (Decide this even if you don’t think there will be a next time.)
<p>
G. I can also teach some of these strategies to some or all of my children.
</p>
<p>
H. When I expect we’re going to have an argument, I’ll try to move to a place that is low risk, such as <b>{{ st.box6 }}</b>. (Try to avoid arguments in the bathroom, garage, kitchen, near weapons, or in rooms without access to an outside door.)
</p>
<p>
I. I will use my judgment and intuition. If the situation is very serious, I can give my partner what he/she wants to calm him/her down.
</p>
{% endfor %}
{% else %}
<h1>No Data</h1>
{% endif %}
</body>
</html>
settings.html
"""
Django settings for dv_project project.
Generated by 'django-admin startproject' using Django 3.0.5.
For more information on this file, see
https://docs.djangoproject.com/en/3.0/topics/settings/
For the full list of settings and their values, see
https://docs.djangoproject.com/en/3.0/ref/settings/
"""
import os
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/3.0/howto/deployment/checklist/
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = 'zg&-*6rqdiqyu4fnq26-w%4)uw#nvlx#9o85)+&z(aaqxy^=_n'
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True
ALLOWED_HOSTS = []
# Application definition
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'myapp.apps.MyappConfig',
]
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
ROOT_URLCONF = 'dv_project.urls'
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
WSGI_APPLICATION = 'dv_project.wsgi.application'
# Database
# https://docs.djangoproject.com/en/3.0/ref/settings/#databases
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
}
}
# Password validation
# https://docs.djangoproject.com/en/3.0/ref/settings/#auth-password-validators
AUTH_PASSWORD_VALIDATORS = [
{
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
},
]
# Internationalization
# https://docs.djangoproject.com/en/3.0/topics/i18n/
LANGUAGE_CODE = 'en-us'
TIME_ZONE = 'UTC'
USE_I18N = True
USE_L10N = True
USE_TZ = True
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/3.0/howto/static-files/
STATIC_URL = '/static/'
CRISPY_TEMPLATE_PACK="bootstrap4"
LOGIN_REDIRECT_URL = 'welcome'
LOGOUT_REDIRECT_URL = "welcome"
If you don't pass the data in any context, then you cannot expect it to be rendered anyhow in the template. It does not take it from view's variables.
If you want data to be in template, then add it to the context:
context = {"form": form, "data": data}
return render(request, 'form.html', context)
or in ANY view, that you want to include {% url 'update' data.id %}:
def index(request):
data = ...
context = {"data": data}
return render(request, 'index.html', context)
PS don't put code in comments. Add it to your Question.
For me, the trick was learning the phrase, "passing the query string" After reading about this on Google I figured it out.
I had to filter for forms in my view. Then, have my .html code filter the request.user's form and added this to {% "url-name" Form.id %} so it passed the form.id into the urls.py, then from there I passed it into my view. So it was like a full circle, starting with the .html document parsing for the right form through the request.user variable. Here is a sample:
views.py
def form_one_page(request):
form = StepOne.objects.filter(user=request.user)
context = { 'form': form,
}
return render(request, 'form_one_page.html', context)
#login_required
def editpost(request, step_one):
"""Form1 Edit post function"""
step1 = StepOne.objects.filter(user=request.user.id) #Gets user id and finds if they have a StepOne form.
step_one = StepOne.objects.get(pk=step_one) #Gets passed the form id by logged in user. See function form_one_page to see how it's passing query string.
form = StepOneForm(instance=step_one)
if request.method == 'POST':
form = StepOneForm(request.POST, instance=step_one)
if form.is_valid():
form.save()
return redirect('user-homepage')
return render(request,'update_form.html', {"form": form, "step1": step1})
user-homepage.html
<tbody>
<td><div class="span12" style="text-align:center">
{% for f in form1 %}
<a href="{% url 'update-post' f.id %}">
{% endfor %}
<button class="wrap_button" >Delete</button>
</a>
</div></td>
</tbody>
urls.py
path('update/<step_one>', views.Step1_Form_Update, name='update-post'),

Django UNIQUE constraint failed: core_organization.name

So I have a model called Organization inside core/models.py. I am trying to implement CRUD Ajax on a single page. Inspired by this post. Every time I save an object of this model I get this error as shown below. I want to have multiple organizations that are unique.
core/models.py
class Organization(models.Model):
name = models.CharField(max_length=255, unique=True)
user = models.ForeignKey(User, on_delete=models.CASCADE)
gstin = models.CharField(max_length=15)
address = models.CharField(max_length=500)
city = models.CharField(max_length=50)
state = models.CharField(max_length=50)
zipcode = models.CharField(max_length=6)
country = models.CharField(max_length=50)
is_billed = models.BooleanField(default=False)
def __str__(self):
return f'{self.name} Organization'
core/forms.py
class OrganizationForm(forms.ModelForm):
class Meta:
model = models.Organization
fields = ('name', 'address', 'state', 'city', 'zipcode', 'country', 'gstin')
core/views.py
def save_organization_form(request, form, template_name):
data = dict()
if request.method == 'POST':
if form.is_valid():
stock = form.save(commit=False)
stock.user = request.user
stock.save()
data['form_is_valid'] = True
organizations = Organization.objects.all()
data['html_book_list'] = render_to_string('core/includes/partial_organization_list.html', {
'organizations': organizations
})
else:
data['form_is_valid'] = False
context = {'form': form}
data['html_form'] = render_to_string(template_name, context, request=request)
return JsonResponse(data)
#login_required(login_url="/accounts/login/")
def organization_create(request):
if request.method == 'POST':
form = OrganizationForm(request.POST)
else:
form = OrganizationForm()
return save_organization_form(request, form, 'core/includes/partial_organization_create.html')
templates/base.html
{% load static %}
<!DOCTYPE html>
<html>
<head>
<title>{% block head_title %}{% endblock %}</title>
{% block extra_head %}
{% endblock %}
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css"
integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
<link href='https://fonts.googleapis.com/css?family=Russo One' rel='stylesheet'>
<link rel="stylesheet" type="text/css" href="{% static 'font/flaticon.css' %}">
<link rel="stylesheet" href="{% static 'css/style.css' %}">
</head>
<body>
{% block body %}
{% if messages %}
<div class="text-center">
<strong>Messages:</strong>
<ul>
{% for message in messages %}
<li>{{message}}</li>
{% endfor %}
</ul>
</div>
{% endif %}
{% block content %}
{% endblock %}
{% endblock %}
{% block extra_body %}
{% endblock %}
<!-- Optional JavaScript -->
<!-- jQuery first, then Popper.js, then Bootstrap JS -->
<script src="https://code.jquery.com/jquery-3.4.1.min.js"
integrity="sha256-CSXorXvZcTkaix6Yvo6HppcZGetbYMGWSFlBw8HfCJo=" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js"
integrity="sha384-ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js"
integrity="sha384-ChfqqxuZUCnJSK3+MXmPNIyE6ZbWh2IMqE241rYiqJxyMiZ6OW/JmZQ5stwEULTy" crossorigin="anonymous"></script>
{% block javascript %}
{% endblock %}
</body>
</html>
templates/core/organization_list.html
{% extends 'base.html' %}
{% load static %}
{% block javascript %}
<script src="{% static 'organizations/js/organizations.js' %}"></script>
{% endblock %}
{% block content %}
<h1 class="page-header">Organizations</h1>
<!-- BUTTON TO TRIGGER THE ACTION -->
<p>
<button type="button"
class="btn btn-primary js-create-book"
data-url="{% url 'organization_create' %}">
<span class="glyphicon glyphicon-plus"></span>
New Organization
</button>
</p>
<table class="table" id="book-table">
<thead>
<tr>
<th>#</th>
<th>Name</th>
<th>Address</th>
<th>State</th>
<th>City</th>
<th>Zipcode</th>
<th>Country</th>
<th>Billing Active</th>
</tr>
</thead>
<tbody>
{% include 'core/includes/partial_organization_list.html' %}
</tbody>
</table>
<!-- THE MODAL WE WILL BE USING -->
<div class="modal fade" id="modal-book">
<div class="modal-dialog">
<div class="modal-content">
</div>
</div>
</div>
{% endblock %}
templates/core/partial_organization_list.html
{% for organization in organizations %}
<tr>
<td>{{ organization.id }}</td>
<td>{{ organization.name }}</td>
<td>{{ organization.address }}</td>
<td>{{ organization.state }}</td>
<td>{{ organization.city }}</td>
<td>{{ organization.zipcode }}</td>
<td>{{ organization.country }}</td>
<td>{{ organization.is_billed }}</td>
<td>
<button type="button"
class="btn btn-warning btn-sm js-update-book"
data-url="{% url 'organization_update' organization.id %}">
<span class="glyphicon glyphicon-pencil"></span> Edit
</button>
<button type="button"
class="btn btn-danger btn-sm js-delete-book"
data-url="{% url 'organization_delete' organization.id %}">
<span class="glyphicon glyphicon-trash"></span> Delete
</button>
</td>
</tr>
{% empty %}
<tr>
<td colspan="8" class="text-center bg-warning">No Organization</td>
</tr>
{% endfor %}
static/organizations/js/organizations.js
$(function () {
$(".js-create-book").click(function () {
$.ajax({
url: '/profile/organization/create/',
type: 'get',
dataType: 'json',
beforeSend: function () {
$("#modal-book").modal("show");
},
success: function (data) {
$("#modal-book .modal-content").html(data.html_form);
}
});
});
});
$("#modal-book").on("submit", ".js-book-create-form", function () {
var form = $(this);
$.ajax({
url: form.attr("action"),
data: form.serialize(),
type: form.attr("method"),
dataType: 'json',
success: function (data) {
if (data.form_is_valid) {
$("#book-table tbody").html(data.html_book_list); // <-- Replace the table body
$("#modal-book").modal("hide"); // <-- Close the modal
}
else {
$("#modal-book .modal-content").html(data.html_form);
}
}
});
return false;
});
$(".js-create-book").click(function () {
var btn = $(this); // <-- HERE
$.ajax({
url: btn.attr("data-url"), // <-- AND HERE
type: 'get',
dataType: 'json',
beforeSend: function () {
$("#modal-book").modal("show");
},
success: function (data) {
$("#modal-book .modal-content").html(data.html_form);
}
});
});
$(function () {
/* Functions */
var loadForm = function () {
var btn = $(this);
$.ajax({
url: btn.attr("data-url"),
type: 'get',
dataType: 'json',
beforeSend: function () {
$("#modal-book").modal("show");
},
success: function (data) {
$("#modal-book .modal-content").html(data.html_form);
}
});
};
var saveForm = function () {
var form = $(this);
$.ajax({
url: form.attr("action"),
data: form.serialize(),
type: form.attr("method"),
dataType: 'json',
success: function (data) {
if (data.form_is_valid) {
$("#book-table tbody").html(data.html_book_list);
$("#modal-book").modal("hide");
}
else {
$("#modal-book .modal-content").html(data.html_form);
}
}
});
return false;
};
/* Binding */
// Create book
$(".js-create-book").click(loadForm);
$("#modal-book").on("submit", ".js-book-create-form", saveForm);
// Update book
$("#book-table").on("click", ".js-update-book", loadForm);
$("#modal-book").on("submit", ".js-book-update-form", saveForm);
// Delete book
$("#book-table").on("click", ".js-delete-book", loadForm);
$("#modal-book").on("submit", ".js-book-delete-form", saveForm);
});
And when I add a new organization I get the following error:
django.db.utils.IntegrityError: UNIQUE constraint failed: core_organization.name
How do I fix this?
I believe your javascript file contains duplicate ajax calls.
There are 3 calls to create your modal:
$(function () {
$(".js-create-book").click(function () {
at the top of your js file. Then the same function in the middle of your js file. And
var loadForm = function ()
which your binding to the click event at the bottom of your script.
In addition there are two functions handling the submission of the form data:
$("#modal-book").on("submit", ".js-book-create-form", function ()
in the top part and
var saveForm = function ()
in the bottom part.
The duplicate regarding the submission of the form can cause the unique constraint error because you are submitting the same data twice. The duplication of the loading of the modal probably does not cause any noticable errors, but is unnecessary load.
The bottom part of your javascript file, i.e. the part beginning with
$(function () {
/* Functions */
should be sufficient.
I think you are having this issue, because of the unique=True constraint on your name field
name = models.CharField(max_length=255, unique=True)
This means that the name is going to be unique for all users, and you will keep getting UNIQUE constraint failed error everytime you add the same name for different users.
To solve this, I suggest using unique_together meta option.
All you have to do, is removing the unique constraint from name field, and adding Meta class with the unique_toghether option to include both the user_id and name fields.
class Organization(models.Model):
name = models.CharField(max_length=255)
user = models.ForeignKey(User, on_delete=models.CASCADE)
address = models.CharField(max_length=1000, default=None)
is_billed = models.BooleanField(default=False)
def __str__(self):
return f'{self.name} Organization'
class Meta:
unique_together = ['name', 'user_id']
Then, python manage.py makemigrations, python manage.py migrate.
The UNIQUE constraint going to remain, but it is going to be for all Organization names related for one user.
If USER1 have organization ORG1, and tried to add another ORG1, it is going to fail, but if USER2 added ORG1 it is going to work successfully.
Try updating the instance rather than form object, Create separate endpoint/logic for updating instance and an separate endpoint/logic to create objects using form
views.py
def save_organization_form(request, form, template_name):
data = dict()
if request.method == 'POST':
if form.is_valid():
stock = form.instance
stock.user = request.user
stock.something = request.something
stock.save()
data['form_is_valid'] = True
organizations = Organization.objects.all()
data['html_book_list'] = render_to_string('core/includes/partial_organization_list.html', {
'organizations': organizations
})
else:
data['form_is_valid'] = False
context = {'form': form}
data['html_form'] = render_to_string(template_name, context, request=request)
return JsonResponse(data)
#login_required(login_url="/accounts/login/")
def organization_create(request):
if request.method == 'POST':
form = OrganizationForm(request.POST)
else:
form = OrganizationForm()
return save_organization_form(request, form, 'core/includes/partial_organization_create.html')

django 2.1 HTML form submitting to db error

i am trying to post the data from html form to my db, however i get the error that the url does not exist. what am trying to do is later on turn the test form into dynamic add fields using HTML and Jquery rather than using formset for ease UI designing and handle it in dango back end.
also note that am assigning the foreign key which is the startup_name by passing it through the url to test view.
the code is as following:
models.py:
class Startup(models.Model):
author = models.ForeignKey(User, on_delete=models.CASCADE)
startup_name = models.CharField('Startup Name', max_length = 32, null = False, blank = False)
class Team (models.Model):
str_team = models.ForeignKey(Startup, on_delete=models.CASCADE)
name = models.CharField('Name',max_length = 32, null = False, blank = False)
position = models.CharField('Title/Position', max_length = 32, null = False, blank = False)
qualification = models.CharField('Degrees/Qualifications', max_length=32,null=False,blank=False)
views.py:
def create_startupform(request):
if request.method == 'POST':
form = startupform(request.POST)
if form.is_valid():
result = form.save(commit=False)
result.author = request.user
result.save()
return redirect('test', startup_id = result.pk)
else:
form = startupform()
return render(request, 'str_name.html', {'form': form})
def test (request, startup_id):
e = Startup.objects.values('startup_name')
if request.method == 'POST':
na = request.POST.get("name")
po = request.POST.get("position")
qu = request.POST.get("qualification")
ref = Team(name = na, position = po, qualification = qu, str_team = e)
ref.save()
return redirect('str_dashboard')
return render(request, 'test.html')
forms.py:
class startupform(forms.ModelForm):
class Meta:
model = Startup
fields = ('startup_name',)
widgets = {
'startup_name': forms.TextInput(attrs = {'class':'form-control'}),
}
def clean(self):
super ( ).clean ( )
startup_name = self.cleaned_data.get ( 'startup_name' )
startup_qs = Startup.objects.filter ( startup_name = startup_name )
if startup_qs.exists ( ):
raise forms.ValidationError ( 'This Startup Already Exist!' )
test.html:
<form id="add-extra" class="form" method="post" action = "{% url 'test' %}">{% csrf_token %}
<div class="form-row profile-row">
<div class="col-md-8 col-lg-12">
<hr />
<h4>Startup Core Team</h4>
<div class="form-row">
<div class="col-sm-12 col-md-6 col-lg-12">
<div class="form-group">
<div class="table-responsive">
<table class="table">
<thead>
<tr>
<th>Name</th>
<th>Position</th>
<th>Qualification</th>
</tr>
</thead>
<tbody>
<tr>
<td><input class="form-control" type="text" name="candidate_name" /></td>
<td><input class="form-control" type="text" name="position"/></td>
<td><input class="form-control" type="text" name="qualification"/></td>
<td><button class="btn btn-primary d-lg-flex align-items-lg-center" type="button" style="margin-top: 4px;margin-left: 15px;background-color: rgb(24,130,7);"><i class="fas fa-plus"></i></button></td>
</tr>
<tr></tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
<hr />
<div class="form-row">
<div class="col-md-12 content-right"><button class="btn btn-primary text-center border rounded d-lg-flex justify-content-lg-end align-items-lg-center form-btn" type="post" style="margin-left: 1040px;padding: 6px;">SAVE </button></div>
</div>
</div>
</div>
URLS:
from django.urls import path
from . import views
urlpatterns = [
path ( 'str_dashboard/' , views.str_dashboard , name = 'str_dashboard' ),
path ( 'create_startupform/' , views.create_startupform, name = 'create_startupform' ),
path('test/', views.test, name='test'),
]
Error:
Page not found (404)
Request Method: GET
Request URL: http://127.0.0.1:8000/test/
Using the URLconf defined in sourcing.urls, Django tried these URL patterns, in this order:
You are trying an url which is not in the urls.py:
urlpatterns = [
...
path('test/<int:startup_id>/', views.test, name='test'),
path('test/', views.test, name='test_base'), # add this
]
The url 'http://127.0.0.1:8000/test/' won't match because it would need to have 'startup_id' attached with your urls.py.
http://127.0.0.1:8000/test/1 would work.
If you do like i wrote above, make sure that your view is taking startup_id as optional. Or use another function for the call without startup_id.

Can't load a form in Django

I need to make a simple form. I can't understand why I don't see it. When I press a button which must show it, I see POST not GET request in my console. Which is not correct. Here is code:
form:
class DeviceAddForm(django.forms.Form):
name = django.forms.CharField(widget = django.forms.TextInput(attrs = {'size':'2','value':'1','class':'device',}))
device_slug = django.forms.CharField(widget = django.forms.HiddenInput())
model_name = django.forms.CharField(widget = django.forms.TextInput(attrs = {'size':'2','value':'1','class':'device',}))
platfrom = django.forms.ComboField(widget = django.forms.CheckboxInput())
sdk = django.forms.ComboField(widget = django.forms.CheckboxInput())
def __init__(self,request=None,*args,**kwargs):
self.request = request
super(DeviceAddForm,self).__init__(*args,**kwargs)
def clean(self):
if self.request:
if not self.request.session.test_cookie_worked():
raise django.forms.ValidationError("Cookies must be enabled")
return self.cleaned_data
saving data:
DEVICE_ID_SESSION_KEY = 'device_id'
def _device_id(request):
if request.session.get(DEVICE_ID_SESSION_KEY,'') == '':
request.session[DEVICE_ID_SESSION_KEY] = _generate_device_id()
return request.session[DEVICE_ID_SESSION_KEY]
def _generate_device_id():
device_id = ''
chars = '0123456789'
device_id_len = 5
for i in range (device_id_len):
device_id +=chars[random.randint(0,len(chars)-1)]
def get_device(request):
return Device.objects.filter(device_id= _device_id(request))
def add_device(request):
postdata = request.POST.copy()
device_slug = postdata.get('device_slug','')
name = postdata.get('name','')
model_name = postdata.get('model_name','')
platform = postdata.get('platform','')
sdk = postdata.get('SDK','')
d = get_list_or_404(Device, slug = device_slug)
dev = Device()
# dev = d
dev.name = name
dev.model_name = model_name
#dev.sdkID
#dev.plID
dev.id = _device_id(request)
dev.save()
view:
#csrf_exempt
def show_device(request, template_name = "onep_web/deviceForm.html"):
d = get_list_or_404(Device,slug = DeviceAddForm.device_slug)
if request.method == 'POST':
postdata = request.POST.copy()
form = DeviceAddForm(request,postdata)
if form.is_valid():
device.add_device(request)
if request.session.test.cookie_worked():
request.session.delete_test_cookie()
url = urlresolvers.reverse('show_device')
return HttpResponseRedirect(url)
else:
form = DeviceAddForm(request=request, label_suffix=':')
form.field['device_slug'].widget.attr['value'] = DeviceAddForm.device_slug
request.session.set_test_cookie()
# return render_to_response(template_name, locals(),csrf(context_instance RequestContext(request)))
return render_to_response(template_name, {'form':form})
urls:
urls form the app
urlpatterns = patterns('onep_web.views',
(r'^$','show_device',{'template_name':'onep_web/deviceForm.html'},'show_device'))
and some more urls:
urls.py from project
from django.conf.urls import patterns, include, url
from django.contrib import admin
admin.autodiscover()
urlpatterns = patterns('',
# Examples:
#url(r'^$', 'welcome_page.home', name='home'),
#url(r'^blog/', include('blog.urls')),
url(r'^admin/', include(admin.site.urls)),
url(r'^welcome_page/', 'one_web.views.welcome_page'),
url(r'^onep_web/', include('onep_web.urls')),
url(r'^device_page/', 'one_web.views.device_page'),
url(r'^configuration_page/', 'one_web.views.configuration_page'),
url(r'^log_page/', 'one_web.views.log_page'),
)
templates :
it's one from which I call the form
<title>OnePK Web Tool - {%block page %}{% endblock %}</title>
</head>
<body>
<div >
<br>
<div> Welcome to OnePK web-tool</div>
</div>
<form >
<br>
<br>
<br>Username:
<input type="text" name="Username">
<br>Password:
<input type="password" name="pwd">
<br>
<br>
{% block content %}
<h4>List of devices and IP addresses:</h4>
<table border="1">
<tr>
<td>Dev1</td>
<td>Dev2</td>
<td>Dev3</td>
<td>Dev4</td>
</tr>
<tr>
<td>{{a.getIP}}</td>
<td>{{a.getIP}}</td>
<td>{{a.getIP}}</td>
<td>{{a.getIP}}</td>
</tr>
</table>
{% endblock %}
<br>
<br>
<br>
<button type="button" onclick="ping()">Ping elenent</button>
<script>
function ping()
{
}
</script>
<br>
<br>
<label>Connection status</label>
<br>
<button type="button" onclick="openDev()">Connect to element</button>
<script>
function openDev()
{
window.open("p2t.html");
}
</script>
</form>
<form method = "post" action = "." class = "device">
{% csrf_token %}
{{form.as_p}}
<br />
<input type="submit" value="Add a new network device" name="submit" alt="Add a new network device"/>
</form>
<div class="cb"></div>
</body>
</body>
</html>
deviceForm:
{ % extends "p1t.html" % }
{ %block content% }
<h1> Add a new Device </h1>
Device info: { { device_data} }
<label for="name">Name</label><input type="text" id = "name" value = ""/>
{ %endblock% }