Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Release v1.8.4 #870

Merged
merged 10 commits into from
Feb 3, 2017
12 changes: 5 additions & 7 deletions netbox/ipam/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -635,16 +635,14 @@ class IPAddressBulkImportView(PermissionRequiredMixin, BulkImportView):

def save_obj(self, obj):
obj.save()
# Update primary IP for device if needed

# Update primary IP for device if needed. The Device must be updated directly in the database; otherwise we risk
# overwriting a previous IP assignment from the same import (see #861).
try:
if obj.family == 4 and obj.primary_ip4_for:
device = obj.primary_ip4_for
device.primary_ip4 = obj
device.save()
Device.objects.filter(pk=obj.primary_ip4_for.pk).update(primary_ip4=obj)
elif obj.family == 6 and obj.primary_ip6_for:
device = obj.primary_ip6_for
device.primary_ip6 = obj
device.save()
Device.objects.filter(pk=obj.primary_ip6_for.pk).update(primary_ip6=obj)
except Device.DoesNotExist:
pass

Expand Down
7 changes: 1 addition & 6 deletions netbox/netbox/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
"the documentation.")


VERSION = '1.8.3'
VERSION = '1.8.4'

# Import local configuration
for setting in ['ALLOWED_HOSTS', 'DATABASE', 'SECRET_KEY']:
Expand Down Expand Up @@ -189,11 +189,6 @@
if LOGIN_REQUIRED:
REST_FRAMEWORK['DEFAULT_PERMISSION_CLASSES'] = ('rest_framework.permissions.IsAuthenticated',)

# Swagger settings (API docs)
SWAGGER_SETTINGS = {
'base_path': '{}/{}api/docs'.format(ALLOWED_HOSTS[0], BASE_PATH),
}

# Django debug toolbar
INTERNAL_IPS = (
'127.0.0.1',
Expand Down
5 changes: 3 additions & 2 deletions netbox/templates/dcim/device.html
Original file line number Diff line number Diff line change
Expand Up @@ -548,9 +548,10 @@
{% block javascript %}
<script type="text/javascript">
function toggleConnection(elem, api_url) {
var url = netbox_api_path + api_url + elem.attr('data') + "/";
if (elem.hasClass('connected')) {
$.ajax({
url: netbox_api_path + api_url + elem.attr('data') + "/",
url: url,
method: 'PATCH',
dataType: 'json',
beforeSend: function(xhr, settings) {
Expand All @@ -569,7 +570,7 @@
});
} else {
$.ajax({
url: api_url + elem.attr('data') + "/",
url: url,
method: 'PATCH',
dataType: 'json',
beforeSend: function(xhr, settings) {
Expand Down
13 changes: 6 additions & 7 deletions netbox/utilities/error_handlers.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,32 +5,31 @@ def handle_protectederror(obj, request, e):
"""
Generate a user-friendly error message in response to a ProtectedError exception.
"""
dependent_objects = e[1]
try:
dep_class = dependent_objects[0]._meta.verbose_name_plural
dep_class = e.protected_objects[0]._meta.verbose_name_plural
except IndexError:
raise e

# Grammar for single versus multiple triggering objects
if type(obj) in (list, tuple):
err_message = "Unable to delete the requested {}. The following dependent {} were found: ".format(
err_message = u"Unable to delete the requested {}. The following dependent {} were found: ".format(
obj[0]._meta.verbose_name_plural,
dep_class,
)
else:
err_message = "Unable to delete {} {}. The following dependent {} were found: ".format(
err_message = u"Unable to delete {} {}. The following dependent {} were found: ".format(
obj._meta.verbose_name,
obj,
dep_class,
)

# Append dependent objects to error message
dependent_objects = []
for o in e[1]:
for o in e.protected_objects:
if hasattr(o, 'get_absolute_url'):
dependent_objects.append('<a href="{}">{}</a>'.format(o.get_absolute_url(), str(o)))
dependent_objects.append(u'<a href="{}">{}</a>'.format(o.get_absolute_url(), o))
else:
dependent_objects.append(str(o))
err_message += ', '.join(dependent_objects)
err_message += u', '.join(dependent_objects)

messages.error(request, err_message)
14 changes: 8 additions & 6 deletions netbox/utilities/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -236,14 +236,15 @@ def __init__(self, csv_form, *args, **kwargs):
if not self.help_text:
self.help_text = 'Enter one line per record in CSV format.'

def utf_8_encoder(self, unicode_csv_data):
for line in unicode_csv_data:
yield line.encode('utf-8')

def to_python(self, value):
# Return a list of dictionaries, each representing an individual record
"""
Return a list of dictionaries, each representing an individual record
"""
# Python 2's csv module has problems with Unicode
if not isinstance(value, str):
value = value.encode('utf-8')
records = []
reader = csv.reader(self.utf_8_encoder(value.splitlines()))
reader = csv.reader(value.splitlines())
for i, row in enumerate(reader, start=1):
if row:
if len(row) < len(self.columns):
Expand All @@ -252,6 +253,7 @@ def to_python(self, value):
elif len(row) > len(self.columns):
raise forms.ValidationError("Line {}: Too many fields (found {}; expected {})"
.format(i, len(row), len(self.columns)))
row = [col.strip() for col in row]
record = dict(zip(self.columns, row))
records.append(record)
return records
Expand Down
25 changes: 18 additions & 7 deletions netbox/utilities/utils.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,26 @@
import six


def csv_format(data):
"""
Encapsulate any data which contains a comma within double quotes.
"""
csv = []
for d in data:
if d in [None, False]:
for value in data:

# Represent None or False with empty string
if value in [None, False]:
csv.append(u'')
elif type(d) not in (str, unicode):
csv.append(u'{}'.format(d))
elif u',' in d:
csv.append(u'"{}"'.format(d))
continue

# Force conversion to string first so we can check for any commas
if not isinstance(value, six.string_types):
value = u'{}'.format(value)

# Double-quote the value if it contains a comma
if u',' in value:
csv.append(u'"{}"'.format(value))
else:
csv.append(d)
csv.append(u'{}'.format(value))

return u','.join(csv)
4 changes: 2 additions & 2 deletions netbox/utilities/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,7 @@ def get_object(self, kwargs):
return get_object_or_404(self.model, pk=kwargs['pk'])

def get_return_url(self, obj):
if hasattr(obj, 'get_absolute_url'):
if obj.pk and hasattr(obj, 'get_absolute_url'):
return obj.get_absolute_url()
return reverse(self.default_return_url)

Expand Down Expand Up @@ -267,7 +267,7 @@ def post(self, request, **kwargs):
if return_url and is_safe_url(url=return_url, host=request.get_host()):
return redirect(return_url)
else:
return redirect(self.default_return_url)
return redirect(self.get_return_url(obj))

return render(request, self.template_name, {
'obj': obj,
Expand Down